2016-11-04 158 views
-1

在python3.5中使用append方法時會出現一些問題。該代碼被呈現使用追加方法的Python淺拷貝和深拷貝

# generate boson basis in lexicographic order 
def boson_basis(L,N): 
basis=[] 
state=[0 for i in range(1,L+1)] 
pos=0 
# initialize the state to |N,0,...,0> 
state[0]=N 
basis.append(state) 
# find the first non-zero position in reverse order 
while state[L-1]<N: 
    for i in range(-2,-L-1,-1): 
     if state[i]>0: 
      pos=L+i 
      break 
    sum=0 
    for i in range(0,pos): 
     sum=sum+state[i] 
    state[pos]=state[pos]-1 
    state[pos+1]=N-sum-state[pos] 
    basis.append(state) 
return basis   

result=boson_basis(3,3) 

預期的結果應該是[[3,0,0],[2,1,0],...,[0,0,3]],但是這個代碼生成與所有元素錯誤的結果是相同的最後一個,即[[0,0,3],...,[0,0,3]]。我使用pdb進行調試,我發現一旦修改了state,已經附加到basis中的前state也會同時更改。這意味着append自動使用deepcopy這超出了我的理解。事實上,如果我們明確使用basis(state.copy()),這個錯誤可以被修復。

在另一方面,下面的簡單代碼顯示沒有錯誤,使用append

x=3 
b=[] 
b.append(x) 
x=x+2 

x之後被改變到x=5b保持不變b=[3]。這真讓我感到困惑,似乎與前一個例子相矛盾。

+2

閱讀關於不可變vs可變對象以及傳值和傳遞引用 –

+0

附加不會複製任何內容,這就是爲什麼您最終在列表中多次顯示相同列表的原因。 – spectras

回答

4

正如已在評論中顯示的那樣,append操作中沒有涉及任何副本。因此你必須自己明確地處理這個問題,例如通過用

basis.append(state[:]) 

的切片操作與:替換

basis.append(state) 

創建的state副本。 注意:它不會複製列表元素 - 只要您只保留普通數字,並且列表中的對象應該沒有問題。