本文翻译自:stackoverflow ,原文链接
想要理解yield 的作用,你必须先理解什么是生成器以及从生成器到迭代器的过程。
Iterables
当你创建一个list,你可以一个一个地读取他的元素,一个一个地读取元素就叫迭代。
>>> mylist = [1, 2, 3]
>>> for i in mylist:
... print(i)
1
2
3
mylist是一个迭代器,当你用一个list推导式,你创造了一个list,也就是一个迭代器。
>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
... print(i)
0
1
4
只要你能使用“for ..in...”结构,那么它就是一个迭代器,例如:lists,strings,files
这些迭代器很方便,因为你能根据你的需要读取他们,但是所有的值都存放在内存,当值很多时你可能并不希望这么做。
Generators
生成器也是迭代器,一种你只能迭代一次的迭代器。生成器并没有把所有值存放在内存中,它在运行时才生产值。
>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
... print(i)
0
1
4
它和迭代器唯一的不同是使用()而不是[],但是只不能使用for i in mygenerator 第二次,因为生成器只能使用一次,它先计算出0,然后忘记这个值,计算出1,最后计算出4,一个接着一个。
Yield
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!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
... print(i)
0
1
4
这是一个使用的例子,当你要返回一个数量很大的集合并且只会读取一次时是很方便的。
要想掌握yield,你必须理解当你调用函数时,你在函数体中定义的代码并不会执行,函数只会返回一个生成器对象,这看上去有点诡异。
你定义在函数体中的代码会在每次for使用生成器时运行
现在来看比较难的部分:
当第一次for调用你函数生成的生成器对象时,它会执行你的函数从开始到yield关键字,然后返回第一次循环的结果。接下来的每次调用都会再一次执行你在函数中定义的循环,并且返回下一个值,知道没有值可以返回。(第一次执行全部函数体,后面每次都只执行循环体)
如果函数运行后生成器返回值是空,那可能是循环已经结束或者不满足if/else条件。
1762

被折叠的 条评论
为什么被折叠?



