2016-05-30 39 views
2

我正在體驗一種從我聽到的在Python中很常見的行爲,但我想知道這是默認設置,以及如何防止這種情況。請看下面的代碼:從外部函數裏面改變外部字典的Python

dic1 = {'a':1, 'b':2} 
lis1 = [1, 2] 

def somefunc(dic): 
    dic.update({'b':20}) 
    return dic 

def otherfunc(lis): 
    lis.append(20) 
    return lis 

for i in range(3): 
    dic2 = dic1 
    lis2 = lis1 
    print(dic2) 
    somefunc(dic2) 
    print(lis2) 
    otherfunc(lis2) 

我們運行此代碼,它輸出

{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 20} 
[1, 2, 20] 
{'a': 1, 'b': 20} 
[1, 2, 20, 20] 

但爲什麼沒有輸出以下?

{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 2} 
[1, 2] 
{'a': 1, 'b': 2} 
[1, 2] 

我覺得它應該輸出這一點,因爲我重新dic2lis2。爲什麼這是默認行爲?一旦進入函數,Python不應該複製dic2嗎?不應該dic2=dic1創建一個dic1的副本,而不是創建一個指向內存中相同位置的不同指針? (如果這確實發生了什麼)

我可以通過更換dic2 = dic1dic2 = dic1.copy()(或添加dic=dic.copy()的功能)防止此問題與dic1發生,但我怎麼用列表做呢?他們沒有複製方法。此外,有沒有辦法讓我在默認情況下防止這種情況發生,而不必在每次處理函數內的字典(或者甚至Pandas數據框等)時都記得使用複製方法?

乾杯

+0

Python中的所有值都通過引用傳遞。有關更完整的解釋,請參閱http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference。 – jstlaurent

回答

1

在Python中,列表是可變的,這意味着LIS2是LIS1的另一個名稱而已,因此它們是同一個對象

這裏有2種方式,使上LIS2 LIS1的副本:

lis2 = lis1[:] 

lis2 = list(lis1) 

我寧願用list()因爲它更具有可讀性。