我在这里有一些可重现的代码:
def test():
a = [0, 1, 2, 3]
for _ in range(len(a)):
a.append(a.pop(0))
for i in range(2,4):
print(a)
yield(i, a)
打印出来:
[1, 2, 3, 0]
[1, 2, 3, 0]
[2, 3, 0, 1]
[2, 3, 0, 1]
[3, 0, 1, 2]
[3, 0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3]
这是我的预期,但当我list(test())
时,我得到了:
[(2, [0, 1, 2, 3]),
(3, [0, 1, 2, 3]),
(2, [0, 1, 2, 3]),
(3, [0, 1, 2, 3]),
(2, [0, 1, 2, 3]),
(3, [0, 1, 2, 3]),
(2, [0, 1, 2, 3]),
(3, [0, 1, 2, 3])]
为什么会这样,我该怎么做才能解决它?
答案 0 :(得分:3)
因为您现在始终返回(i,a)
a
是参考到列表中。因此,您不断将引用返回到相同的列表。 print
语句没有问题,因为它会立即打印a
的状态。
您可以返回列表的副本,例如:
def test():
a = [0, 1, 2, 3]
for _ in range(len(a)):
a.append(a.pop(0))
for i in range(2,4):
print(a)
yield(i, list(a))
答案 1 :(得分:3)
每次都会产生相同的列表,因此调用者的列表只有一堆对该列表的引用,每次调用时都会更新。当您屈服时,您需要复制列表:
def test():
a = [0, 1, 2, 3]
for _ in range(len(a)):
a.append(a.pop(0))
for i in range(2,4):
print(a)
yield(i, a[:])
答案 2 :(得分:1)
显式更好隐式:
import copy
def test():
a = [0, 1, 2, 3]
for _ in range(len(a)):
a.append(a.pop(0))
for i in range(2,4):
print(a)
yield(i, copy.copy(a))
答案 3 :(得分:1)
您最终得到了一个元组列表,元组的第二个元素是相同的列表。您可能会注意到它们都等同于生成器生成的最后一个列表,而不是第一个列表;列表正在改变,但元组都引用了同一个。
为清楚起见,请尝试修改其中一个列表。例如,如果您运行l[0][1].append(4)
,则会获得
[(2, [0, 1, 2, 3, 4]),
(3, [0, 1, 2, 3, 4]),
(2, [0, 1, 2, 3, 4]),
(3, [0, 1, 2, 3, 4]),
(2, [0, 1, 2, 3, 4]),
(3, [0, 1, 2, 3, 4]),
(2, [0, 1, 2, 3, 4]),
(3, [0, 1, 2, 3, 4])]
所有列表都附加了4个,因为只有一个列表。
如果要返回副本,有几种方法。您可以yield (i, a[:])
(使用切片表示法获取副本),yield (i, list(a))
(使用list
构造函数获取副本)或yield (i, copy.copy(a))
(使用copy
}模块)。