2011-04-08 111 views
1

我有一些Python代碼依賴於傳遞一些lambda表達式,並且它們被複制到一些不同的地方,但我發現當我將它們從列表中彈出時,它們就會從所有其他列表中奇蹟般地消失。我不知道這是否是一個錯誤。我會注意到,我在CPython上運行這個。爲什麼我的lambda消失了?

下面是一些代碼來說明我的觀點:

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是否在做引用計數,新名單應該增加引用計數,但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) 

仍然沒有去。

任何人都知道這裏發生了什麼?

回答

4

list.pop就地修改列表。因此,所有參考清單的人都會看到相同的變化。您不會在第二個存儲副本,只是將多個引用存儲到一個列表中,然後在第一個循環中將其清空。

您可以通過a[:]複製列表(這是從一開始就切片年底,包括兩個) - 注意,這是一個shallow copy - 並與copy模塊幾乎一切(包括你自己的類的實例)。

+2

如果你想把'b'的副本附加到'c',你可以說'c.append(b [:])''。 – dfan 2011-04-08 19:35:12

+0

謝謝。使用「複製」模塊解決了我的問題。 – supercheetah 2011-04-08 19:44:02

2

你有你的示例設置的方式,唯一持有對您的lambdas的引用是listBC持有參考listB而不是B裏面的lambda。當你彈出B的lambda表達式時,不會引用lambda表達式。剩下的是C,其中B現在是空的。


此外,一個很好的提示是指出了另一個答案的評論:

信用:Dfan

如果要追加b鍵 ℃的副本,你可以說c.append(b [:])

1
import copy 
for i in range(3): 
    b.append(copy.deepcopy(a)) 
for i in range(3): 
    c.append(copy.deepcopy(b)) 

ÿ ou只是創建引用(淺拷貝),才能真正複製值,就像您期望您必須使用「深層拷貝」一樣。