看这个answer,似乎使用列表推导(或for
的{{1}}循环)等效于在迭代器上调用append
。由于也generators are iterators,我希望生成器也一样。但是,如果您运行
list(..)
def permute(xs, count, low = 0):
if low + 1 >= count:
yield xs
else:
for p in permute(xs, low + 1):
yield p
for i in range(low + 1, count):
xs[low], xs[i] = xs[i], xs[low]
for p in permute(xs, low + 1):
yield p
xs[low], xs[i] = xs[i], xs[low]
print("Direct iteration")
for x in permute([1, 2], 2):
print(x)
print("Listing")
for x in list(permute([1, 2], 2)):
print(x)
为什么会这样?
答案 0 :(得分:3)
您正在反复修改并产生相同的列表xs
。生成器运行时,列表内容正在更改。看起来它起作用了,因为尽管每个print(x)
都打印相同的列表对象,但是该对象每次都具有不同的内容。
另一方面,第二个循环使生成器运行到完成并收集所有列表引用。 然后它会打印出列表-除非它们都是相同的列表,所以每一行都是相同的!
将两行print(x)
更改为print(x, id(x))
,您将明白我的意思。 ID号将完全相同。
Direct iteration
[1, 2] 140685039497928
[2, 1] 140685039497928
Listing
[1, 2] 140685039497736
[1, 2] 140685039497736
一个快速的解决方法是产生列表的副本,而不是原始列表。 yield p
很好,但是yield xs
应该变成:
yield xs[:]
通过该修复,结果如预期的那样:
Direct iteration
[1, 2] 140449546108424
[2, 1] 140449546108744
Listing
[1, 2] 140449546108424
[2, 1] 140449546108808
两个循环的结果相同,并且ID号不同。