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

sir*_*ark 4 python generator

我有一个函数(f)yield.我有一份清单(E).
如果我尝试E += f()然后f()不返回生成器对象,而是运行该函数,该函数抛出异常,因为一些全局变量尚未就绪.

为了阻止任何评论,我知道这E += f()是错误的,但它为我的问题提供了一个例子.如果我做正确的事情,E += [f()]或者E.append(f())然后f()返回一个生成器对象,并且在调用f()生成器对象的next方法之前不会评估代码.

我的问题是,为什么f()要在错误的情况下进行评估,为什么会出现异常,而不是"函数对象不可迭代".

sir*_*ark 6

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

E += f() 是列表连接,这意味着)f的结果(必须是可迭代,并且此外,该迭代器被评估为的级联的一部分,这意味着f()的.下一个被称为

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

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


Fre*_*Foo 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]
Run Code Online (Sandbox Code Playgroud)

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