我有一些Python代码依赖于传递一些lambda,并且它们被复制到几个不同的地方,但是我发现当我从列表中弹出它们时,它们只是神奇地从所有其他列表中消失。我不知道这是不是一个bug。我会注意到我在CPython上运行它。
以下是一些代码来说明我的观点:
a = lambda x: x+x*3
b = []
c = []
for i in range(3):
b.append(a)
for i in range(3):
c.append(b)
while b:
print b.pop()(5)
for d in c:
while d:
print d.pop()(10)
如果Python正在进行引用计数,那么新列表应该增加引用计数,但lambdas只是不断消失。
我甚至试过这个,以便每次通过第一个循环创建一个新的lambda实例:
b = []
c = []
for i in range(3):
b.append(lambda x: x+x*3)
for i in range(3):
c.append(b)
while b:
print b.pop()(5)
for d in c:
while d:
print d.pop()(10)
仍然没有。
任何人都知道这里发生了什么?
答案 0 :(得分:4)
list.pop
就地修改列表。因此,每个参考该列表的人都会看到相同的变化。你不是在第二个存储副本,你只是将几个引用存储到一个列表中,然后在第一个while
循环中清空。
您可以通过a[:]
复制列表(这是从开头到结尾的切片,包括两者) - 请注意它是shallow copy - 几乎所有内容(包括您自己的类的实例)使用copy
模块。
答案 1 :(得分:2)
您进行示例设置的方式,唯一引用lambdas
的{{1}} list
。 B
对C
内的lambdas提及list
B
。当您从B
中弹出lambda时,不会保留对lambda的引用。您剩下的是B
,其中C
的引用现在为空。
此外,另一个答案的评论中指出了一个很好的提示:
信用:Dfan
如果要附加b的副本 c,你可以说c.append(b [:])
答案 2 :(得分:1)
import copy
for i in range(3):
b.append(copy.deepcopy(a))
for i in range(3):
c.append(copy.deepcopy(b))
您只是创建引用(浅层复制),以真正复制您希望必须使用“深层复制”的值。