什么时候发电机不是发电机?为什么用yield调用我的函数有时不返回生成器对象

时间:2012-01-26 09:53:31

标签: python generator

我有(f)函数yield。我有一个列表(E)
如果我尝试E += f(),那么f()不返回生成器对象,而是运行该函数,该函数抛出异常,因为某些全局变量尚未就绪。

为了阻止任何评论,我知道E += f()是错误的,但它提供了我的问题的一个例子。如果我做正确的事E += [f()]E.append(f())那么f()返回一个生成器对象,并且在调用生成器对象的f()方法之前不会评估next的代码。
我的问题是,为什么f()在错误的情况下被评估,为什么不是引发异常而不是“函数对象不可迭代”。

2 个答案:

答案 0 :(得分:6)

因为表达式f()调用fE += f()将运行生成器直到结束并将其生成的值追加到E。它根本不是“错误的”,但它确实需要一个完全有效的f,它产生有限数量的值:

>>> E = [1,2,3]
>>> def f():
...  yield 4
...  yield 5
...
>>> E += f()
>>> E
[1, 2, 3, 4, 5]

相比之下,E += [f()]将调用f,但随后在代码的第一行之前停止,因为然后解释器具有足够完整的对象,即生成器对象,以存储在单个代码中。元素列表[f()]。只有在稍后,当您从E[-1]请求更多元素时,才会编写第一个yield运行代码并引发异常。

答案 1 :(得分:5)

好的,所以当我输入问题的最后一行时,我想我想出来了。

E += f()是列表并置,这意味着f()的结果必须是可迭代的,而且,迭代器被评估为连接的一部分,意思是f()。next被称为

E += [f()]将生成器对象包装在一个可迭代的对象(列表)中,这是评估的外部列表

E.append(f())不是列表的串联,而是添加一个元素(其可迭代属性,如果有的话,被忽略),因此生成器对象永远不会被评估