附加到列表并产生列表的Python

附加到列表并产生列表的Python,python,generator,Python,Generator,这是怎么回事?为什么list(f(seq))返回的不是f生成的元素列表 >>> def f(seq): ... a = [] ... for i in seq: ... yield a ... a.append(i) ... >>> f([1,2,3]) <generator object f at 0x1066c7aa0> >>> b = f([1,2,3]) >>> b.next()

这是怎么回事?为什么
list(f(seq))
返回的不是
f
生成的元素列表

>>> def f(seq):
...   a = []
...   for i in seq:
...     yield a
...     a.append(i)
...
>>> f([1,2,3])
<generator object f at 0x1066c7aa0>
>>> b = f([1,2,3])
>>> b.next()
[]
>>> b.next()
[1]
>>> b.next()
[1, 2]
>>> b.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(f([1,2,3]))
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
def f(序列号): ... a=[] ... 对于下文中的i: ... 产生 ... a、 附加(i) ... >>>f([1,2,3]) >>>b=f([1,2,3]) >>>b.下一步() [] >>>b.下一步() [1] >>>b.下一步() [1, 2] >>>b.下一步() 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 停止迭代 >>>列表(f([1,2,3])) [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
您已经在函数中生成了对列表
a
的完整引用。当调用
列表(f([1,2,3])
时,结果只是
[a,a]
,而
a
的最终形式是
[1,2,3]

如果您保存了
f.next()
调用的所有结果,那么这也没有什么不同

>>> v1 = b.next()
>>> v2 = b.next()
>>> v1
[1]
>>> v2
[1]
>>> v3 = b.next()
>>> v4 = b.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> v1
[1, 2, 3]
v1=b.next() >>>v2=b.next() >>>v1 [1] >>>v2 [1] >>>v3=b.next() >>>v4=b.next() 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 停止迭代 >>>v1 [1, 2, 3]
同样,这是正确的,因为生成了
a
,并且是对函数
f
中相同内部列表的相同引用。您生成的是在生成器中创建的列表,而不是列表的副本。列表是可变的,因此对该列表的任何更改都会反映在对该列表的所有引用中
考虑这一点:

>>> a = [[]]*4      # Create a list of 4 references to the same list
>>> a[0].append(1)  # Add 1 the first reference
>>> a
[[1], [1], [1], [1]]

消除此依赖关系的一个解决方案是在您让步时浅层复制列表,将
yield a
替换为
yield a[:]
。这需要大量的复制,但是如果你想返回独立的列表,这是必要的。@achampion必须回滚你的编辑,因为你实际上没有在Python shell中运行他的代码来查看输出是否完全正确。已确认,抱歉。