2016-12-19 23 views
4

我知道發送列表時,作爲參數傳遞給函數,函數的變化將改變列表,例如:改變,因爲函數參數列表的價值

p=[[3, 4], [2, 3]] 
node=[5,3] 

def foo(node, p_as_list): 
    p_as_list.append(node) 


foo(node, p) 
print(p) #p changes 

阻止我用拷貝的變化( ):

p=[[3, 4], [2, 3]] 
node=[5,3] 

def foo(node, p_as_list): 
    p_as_list.append(node) 

#this line 
foo(node, p.copy()) 
print(p) # without changes 

,但如果我改變函數是這樣的:

p=[[3, 4], [2, 3]] 
node=[5,3] 

def foo(node, p_as_list): 
    #this line 
    p_as_list=p_as_list[-1] 
    p_as_list.append(node) 

foo(node, p.copy()) 
print(p) 

則p將再次改變,我無法理解爲什麼會發生?要做到這一點

+5

這是因爲你做的,而不是一深一淺拷貝。您正在複製對那些仍在修改的內部列表的引用。請參閱[深拷貝和淺拷貝之間的區別是什麼?](http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow - 複製) – SuperBiasedMan

+0

我需要一個有效的內存方式來傳遞列表功能,我需要的列表不會改變,有沒有更好的解決方案? –

+2

我不確定你的具體情況,但你可以嘗試複製被修改列表的部分。例如,如果您已經完成了'p_as_list = p_as_list [-1] .copy()',原始列表將保持不變,並且不會浪費存儲器複製原始列表的每個方面。你甚至可以刪除傳遞給函數的'p.copy()'部分。 – SuperBiasedMan

回答

1

插入一些調試print小號幫助識別問題:

p=[[3, 4], [2, 3]] 
node=[5,3] 

def foo(node, p_as_list): 
    #this line 
    print('p', id(p_as_list)) 
    p_as_list=p_as_list[-1] 
    print('pm1', id(p_as_list)) 
    p_as_list.append(node) 

print('p', id(p)) 
print('pm1', id(p[-1])) 
foo(node, p.copy()) 
print(p) 

此打印:

p 1872370555144 
pm1 1872370556232 
p 1872370108872 
pm1 1872370556232 
[[3, 4], [2, 3, [5, 3]]] 

請注意,idp[-1]並沒有改變,您操作的是相同的list。這是因爲您只使用list.copy()時創建了一個淺拷貝

代替copy荷蘭國際集團的全名單我會建議只是修改部分複製的功能內:

p=[[3, 4], [2, 3]] 
node=[5,3] 

def foo(node, p_as_list): 
    #this line 
    p_as_list=p_as_list[-1].copy() # copy here! 
    p_as_list.append(node) 

foo(node, p) # don't copy here! 
print(p) 
0

一種方法是使用deepcopy的

參考庫路徑:https://docs.python.org/2/library/copy.html

import copy 

p = [[3, 4], [2, 3]] 
node = [5,3] 

def foo(node, p_as_list): 
    p_as_list = p_as_list[-1] 
    p_as_list.append(node) 

foo(node, copy.deepcopy(p)) 

print(p)