本文转自stackoverflow中一个问题的译文
原文:http://pyzh.readthedocs.io/en/latest/the-python-yield-keyword-explained.html
mylist
是一个可迭代的对象。当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代的对象:
>>> 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
注意你之后不能再使用for i in mygenerator
了
yield
是一个类似 return
的关键字,只是这个函数返回的是个生成器>>> def createGenerator() :
... mylist = range(3)
... for i in mylist :
... yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
0xb7555c34>
>>> for i in mygenerator:
... print(i)
0
1
4
第一次迭代中你的函数会执行,从开始到达 yield 关键字,然后返回 yield 后的值作为第一次迭代的返回值. 然后,每次执行这个函数都会继续执行你在函数内部定义的那个循环的下一次,再返回那个值,直到没有可以返回的。
>>> 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())
'exceptions.StopIteration'>
>>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs
>>> print(wall_street_atm.next())
'exceptions.StopIteration'>
>>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty
>>> print(corner_street_atm.next())
'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
...