yield
回报无论对象传递给它,即使该对象是一个序列或一个生成器或其他迭代器。因此:
>>> def g():
... yield [1,2,3]
... yield 1
... yield 2
... yield 3
...
>>> gen = g()
>>> gen.next()
[1, 2, 3]
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
3
>>> gen.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
__iter__
当需要在对象的内容的迭代器(如在一当它是一个for x in obj
构建体的一部分)被称为一个对象上。你可以使用yield
来创建一个生成器(因为生成器是迭代器),但在本例中你不需要。下面的工作还有:
def __iter__(self):
return iter(self.__a)
如果你想使用yield
,并且希望迭代器Vect
对象通过向量的内容移动,你必须产量每个值分别:
def __iter__(self):
for i in self.__a:
yield i
的yield
意味着__iter__
将返回一个发电机和发电机对象调用next()
将在其最后一次离开,因为它通过__a
迭代点恢复功能。
=======
在回答关于Python如何跟踪,其中发电机是执行额外的问题,我相信它使用f_lasti(==“最后一条指令”)的生成器的gi_frame属性(生成器,与普通函数不同,它们带有执行框架)。这是一个有点围绕模具的显示值如何变化:
>>> import dis
>>> def g():
... yield 1
... for i in range(10):
... yield i*2
...
>>> gen = g()
>>> dis.dis(gen.gi_code)
2 0 LOAD_CONST 1 (1)
3 YIELD_VALUE
4 POP_TOP
3 5 SETUP_LOOP 29 (to 37)
8 LOAD_GLOBAL 0 (range)
11 LOAD_CONST 2 (10)
14 CALL_FUNCTION 1
17 GET_ITER
>> 18 FOR_ITER 15 (to 36)
21 STORE_FAST 0 (i)
4 24 LOAD_FAST 0 (i)
27 LOAD_CONST 3 (2)
30 BINARY_MULTIPLY
31 YIELD_VALUE
32 POP_TOP
33 JUMP_ABSOLUTE 18
>> 36 POP_BLOCK
>> 37 LOAD_CONST 0 (None)
40 RETURN_VALUE
>>> gen.gi_frame.f_lasti ## -1 because we haven't started yet
-1
>>> gen.next()
1
>>> gen.gi_frame.f_lasti
3
>>> gen.gi_frame.f_locals
{}
>>> gen.next()
0
>>> gen.gi_frame.f_lasti , gen.gi_frame.f_locals
(31, {'i': 0})
>>> gen.next()
2
>>> gen.gi_frame.f_lasti , gen.gi_frame.f_locals
(31, {'i': 1})
>>>
注意f_lasti值如何对应于反汇编代码编号的行,最后的产量是在:从那个时候当发生器重新启动重新进入。
带有yield语句的方法是一个迭代器。产生的值是迭代器访问的值。 – robert
顺便问一下,您是否知道Python如何记住哪个是迭代器产生的最后一个元素? – Michal
“但是在我的例子中,我没有任何生成器” - 一个包含yield语句的函数是一个生成器。你期望什么需要?一个generator **表达式**?这只是一种发电机。 –