我有(f)
函数yield
。我有一个列表(E)
。
如果我尝试E += f()
,那么f()
不返回生成器对象,而是运行该函数,该函数抛出异常,因为某些全局变量尚未就绪。
为了阻止任何评论,我知道E += f()
是错误的,但它提供了我的问题的一个例子。如果我做正确的事E += [f()]
或E.append(f())
那么f()返回一个生成器对象,并且在调用生成器对象的f()
方法之前不会评估next
的代码。
我的问题是,为什么f()
在错误的情况下被评估,为什么不是引发异常而不是“函数对象不可迭代”。
答案 0 :(得分:6)
因为表达式f()
调用f
,E += 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())
不是列表的串联,而是添加一个元素(其可迭代属性,如果有的话,被忽略),因此生成器对象永远不会被评估