我有一个如下定义的生成器:
def gen():
r = [0]
yield r
r[0] = 1
yield r
r[0] = 2
yield r
它将产生三个列表,其中一个元素从 0 到 2:
>>> a = gen()
>>> next(a)
[0]
>>> next(a)
[1]
>>> next(a)
[2]
>>> next(a)
Traceback (most recent call last):
File "<pyshell#313>", line 1, in <module>
next(a)
StopIteration
现在,当我从生成器中创建列表时,我得到了这个:
>>> list(gen())
[[2], [2], [2]]
也就是说,它似乎每次都会产生最后一个计算值。
这是一个Python错误还是我遗漏了什么?
最佳答案
这不是错误,它完全按照您的指示执行。您多次生成同一个对象,因此您会获得对该对象的多个引用。在第一个代码片段中看不到三个 [2]
的唯一原因是 Python 不会及时返回并更改以前的输出以匹配对象发生突变的情况。尝试将显式调用 next
时获得的值存储在变量中,并在最后检查它们 - 您将得到相同的结果。
只有在迭代器再次前进后没有使用生成值时,这样的迭代器才有用。因此我通常会避免它,因为它在尝试预先计算部分或全部结果时会产生意想不到的结果(这也意味着它破坏了各种有用的技巧,例如 itertools.tee 和可迭代解包)。
关于python3 : list() from generator: strange behaviour when yielding item-changed lists,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7503639/