python - Que fait le mot clé de rendement

Mots clés : pythoniteratorgeneratoryieldcoroutinepython

meilleur 5 Réponses python - Que fait le mot clé de rendement

vote vote

93

>>> mylist = [1, 2, 3] >>> for i in mylist: ...    print(i) 1 2 3 
>>> mylist = [x*x for x in range(3)] >>> for i in mylist: ...    print(i) 0 1 4 
>>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ...    print(i) 0 1 4 
>>> def create_generator(): ...    mylist = range(3) ...    for i in mylist: ...        yield i*i ... >>> mygenerator = create_generator() # create a generator >>> print(mygenerator) # mygenerator is an object! <generator object create_generator at 0xb7555c34> >>> for i in mygenerator: ...     print(i) 0 1 4 
# Here you create the method of the node object that will return the generator def _get_child_candidates(self, distance, min_dist, max_dist):      # Here is the code that will be called each time you use the generator object:      # If there is still a child of the node object on its left     # AND if the distance is ok, return the next child     if self._leftchild and distance - max_dist < self._median:         yield self._leftchild      # If there is still a child of the node object on its right     # AND if the distance is ok, return the next child     if self._rightchild and distance + max_dist >= self._median:         yield self._rightchild      # If the function arrives here, the generator will be considered empty     # there is no more than two values: the left and the right children 
# Create an empty list and a list with the current object reference result, candidates = list(), [self]  # Loop on candidates (they contain only one element at the beginning) while candidates:      # Get the last candidate and remove it from the list     node = candidates.pop()      # Get the distance between obj and the candidate     distance = node._get_dist(obj)      # If distance is ok, then you can fill the result     if distance <= max_dist and distance >= min_dist:         result.extend(node._values)      # Add the children of the candidate in the candidate's list     # so the loop will keep running until it will have looked     # at all the children of the children of the children, etc. of the candidate     candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))  return result 
>>> a = [1, 2] >>> b = [3, 4] >>> a.extend(b) >>> print(a) [1, 2, 3, 4] 
>>> class Bank(): # Let's create a bank, building ATMs ...    crisis = False ...    def create_atm(self): ...        while not self.crisis: ...            yield "$100" >>> hsbc = Bank() # When everything's ok the ATM gives you as much as you want >>> corner_street_atm = hsbc.create_atm() >>> print(corner_street_atm.next()) $100 >>> print(corner_street_atm.next()) $100 >>> print([corner_street_atm.next() for cash in range(5)]) ['$100', '$100', '$100', '$100', '$100'] >>> hsbc.crisis = True # Crisis is coming, no more money! >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> wall_street_atm = hsbc.create_atm() # It's even true for new ATMs >>> print(wall_street_atm.next()) <type 'exceptions.StopIteration'> >>> hsbc.crisis = False # The trouble is, even post-crisis the ATM remains empty >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> brand_new_atm = hsbc.create_atm() # Build a new one to get back in business >>> for cash in brand_new_atm: ...    print cash $100 $100 $100 $100 $100 $100 $100 $100 $100 ... 
>>> horses = [1, 2, 3, 4] >>> races = itertools.permutations(horses) >>> print(races) <itertools.permutations object at 0xb754f1dc> >>> print(list(itertools.permutations(horses))) [(1, 2, 3, 4),  (1, 2, 4, 3),  (1, 3, 2, 4),  (1, 3, 4, 2),  (1, 4, 2, 3),  (1, 4, 3, 2),  (2, 1, 3, 4),  (2, 1, 4, 3),  (2, 3, 1, 4),  (2, 3, 4, 1),  (2, 4, 1, 3),  (2, 4, 3, 1),  (3, 1, 2, 4),  (3, 1, 4, 2),  (3, 2, 1, 4),  (3, 2, 4, 1),  (3, 4, 1, 2),  (3, 4, 2, 1),  (4, 1, 2, 3),  (4, 1, 3, 2),  (4, 2, 1, 3),  (4, 2, 3, 1),  (4, 3, 1, 2),  (4, 3, 2, 1)] 
vote vote

84

for x in mylist:     ...loop body... 
def f123():     yield 1     yield 2     yield 3  for item in f123():     print item 
vote vote

77

def some_function():     for i in xrange(4):         yield i  for i in some_function():     print i 
class it:     def __init__(self):         # Start at -1 so that we get 0 when we add 1 below.         self.count = -1      # The __iter__ method will be called once by the 'for' loop.     # The rest of the magic happens on the object returned by this method.     # In this case it is the object itself.     def __iter__(self):         return self      # The next method will be called repeatedly by the 'for' loop     # until it raises StopIteration.     def next(self):         self.count += 1         if self.count < 4:             return self.count         else:             # A StopIteration exception is raised             # to signal that the iterator is done.             # This is caught implicitly by the 'for' loop.             raise StopIteration  def some_func():     return it()  for i in some_func():     print i 
iterator = some_func() try:     while 1:         print iterator.next() except StopIteration:     pass 
vote vote

67

generator = myYieldingFunction(...)  # basically a list (but lazy) x = list(generator)  # evaluate every element into a list     generator        v [x[0], ..., ???]           generator              v [x[0], x[1], ..., ???]                 generator                    v [x[0], x[1], x[2], ..., ???]                         StopIteration exception [x[0], x[1], x[2]]     done 
def makeRange(n):     # return 0,1,2,...,n-1     i = 0     while i < n:         yield i         i += 1  >>> makeRange(5) <generator object makeRange at 0x19e4aa0> 
>>> list(makeRange(5)) [0, 1, 2, 3, 4] 
# return a list                  #  # return a generator def makeRange(n):                #  def makeRange(n):     """return [0,1,2,...,n-1]""" #      """return 0,1,2,...,n-1"""     TO_RETURN = []               #      i = 0                        #      i = 0     while i < n:                 #      while i < n:         TO_RETURN += [i]         #          yield i         i += 1                   #          i += 1     return TO_RETURN             #   >>> makeRange(5) [0, 1, 2, 3, 4] 
#                  < ITERABLE > >>> [x+10 for x in makeRange(5)] [10, 11, 12, 13, 14] 
>>> x=iter(range(5)) >>> next(x)  # calls x.__next__(); x.next() is deprecated 0 >>> next(x) 1 >>> next(x) 2 >>> next(x) 3 >>> next(x) 4 >>> next(x) Traceback (most recent call last):   File "<stdin>", line 1, in <module> StopIteration 
def interactiveProcedure():     userResponse = yield makeQuestionWebpage()     print('user response:', userResponse)     yield 'success'  coroutine = interactiveProcedure() webFormData = next(coroutine)  # same as .send(None) userResponse = serveWebForm(webFormData)  # ...at some point later on web form submit...  successStatus = coroutine.send(userResponse) 
> x = myRange(5) > list(x) [0, 1, 2, 3, 4] > list(x) [] 
vote vote

60

>>> def func(): ...     yield 'I am' ...     yield 'a generator!' ...  >>> type(func)                 # A function with yield is still a function <type 'function'> >>> gen = func() >>> type(gen)                  # but it returns a generator <type 'generator'> >>> hasattr(gen, '__iter__')   # that's an iterable True >>> hasattr(gen, 'next')       # and with .next (.__next__ in Python 3) True                           # implements the iterator protocol. 
>>> import collections, types >>> issubclass(types.GeneratorType, collections.Iterator) True 
>>> isinstance(gen, types.GeneratorType) True >>> isinstance(gen, collections.Iterator) True 
>>> list(gen) ['I am', 'a generator!'] >>> list(gen) [] 
>>> list(func()) ['I am', 'a generator!'] 
def func(an_iterable):     for item in an_iterable:         yield item 
def func(an_iterable):     yield from an_iterable 
def bank_account(deposited, interest_rate):     while True:         calculated_interest = interest_rate * deposited          received = yield calculated_interest         if received:             deposited += received   >>> my_account = bank_account(1000, .05) 
>>> first_year_interest = next(my_account) >>> first_year_interest 50.0 
>>> next_year_interest = my_account.send(first_year_interest + 1000) >>> next_year_interest 102.5 
 def money_manager(expected_rate):     # must receive deposited value from .send():     under_management = yield                   # yield None to start.     while True:         try:             additional_investment = yield expected_rate * under_management              if additional_investment:                 under_management += additional_investment         except GeneratorExit:             '''TODO: write function to send unclaimed funds to state'''             raise         finally:             '''TODO: write function to mail tax info to client'''           def investment_account(deposited, manager):     '''very simple model of an investment account that delegates to a manager'''     # must queue up manager:     next(manager)      # <- same as manager.send(None)     # This is where we send the initial deposit to the manager:     manager.send(deposited)     try:         yield from manager     except GeneratorExit:         return manager.close()  # delegate? 
my_manager = money_manager(.06) my_account = investment_account(1000, my_manager) first_year_return = next(my_account) # -> 60.0 
next_year_return = my_account.send(first_year_return + 1000) next_year_return # 123.6 
my_account.close() 
import sys try:     raise ValueError except:     my_manager.throw(*sys.exc_info()) 
Traceback (most recent call last):   File "<stdin>", line 4, in <module>   File "<stdin>", line 6, in money_manager   File "<stdin>", line 2, in <module> ValueError 
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |                      ('=' (yield_expr|testlist_star_expr))*) ... yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist 

Questions similaires