2017-11-11 72 views
0

我正在Python中編寫腳本來模擬辯論者的比賽。但我遇到了這個奇怪的錯誤,看起來像通過引用問題,但有一些行爲,不應該通過引用的影響。Python通過引用和字典副本傳遞

基本上,團隊是一個團隊字典,每個團隊都有一堆領域,包括勝利和失敗領域,當我第一次建立團隊時,這兩個領域都被初始化爲0。

然後df.apda_tournament()接收一個團隊詞典,並根據模擬改變團隊的勝負,並返回更新的團隊詞典。

由於參考作品的傳遞方式,團隊字典被傳遞到df.apda_tournament()中,並且返回的一個最終都被修改,因爲該函數改變了傳入字典中記錄的勝負,並返回它。因此:

apda_results == apda_teams 

正如我所預期的那樣返回True。

奇怪的是,df.apda_tournament()也改變了原始團隊字典apda_teams是副本。所以它最終成爲:

apda_teams == teams 

也返回true。這很奇怪,因爲它看起來像apda_teams,當我聲明它只是對團隊的引用而不是副本時,我不會指望它,因爲我將它聲明爲函數之外。

有人可以解釋到底發生了什麼嗎?另外我該如何避免這種情況,apda_teams實際上是團隊字典的唯一副本,而不僅僅是對內存中記錄的引用?

附在下面是代碼:

import debate_functions as df 

dbtr_num = 64 
team_num = dbtr_num/2 
dbtr_mn_mn = 200 
dbtr_mn_std = 80 
dbtr_std_mn = 80 
dbtr_std_std = 60 
judge_bias = 70 

dbtrs = df.make_debaters(dbtr_num, dbtr_mn_mn, dbtr_mn_std, dbtr_std_mn, dbtr_std_std) 
teams = df.make_teams(dbtrs, dbtr_mn_mn, dbtr_mn_std) 
print(teams) 
apda_teams = teams 
para_teams = teams 

apda_results = df.apda_tournament(5, apda_teams, judge_bias) 
print('Check this') 
print(apda_results == apda_teams) 
print(apda_teams == teams) 

運行它返回:

Check this 
True 
True 
+0

通過引用或值的概念,Python不能像C一樣工作。長話短說:如果你沒有明確地複製一本字典,它將在通話和分配中保持相同的對象。 –

+0

是的,我明白了,我特別想知道這個代碼中的團隊,因爲我明確地將它複製到apda_teams,然後只在apda_teams上調用函數,但團隊正在修改。 –

回答

0

在Python列表,字典是可變的,(我們可以修改的內容)。所以,無論何時您將列表,字典傳遞給任何函數或分配給任何變量,都會指向給定變量的引用。

字符串,數字,元組是不可變的(我們不能修改內容)。所以,只要你字符串元組,數字到任何函數或分配給任何變量,那麼它只是複製值。

+0

是的,我明白了,這就是爲什麼(apda_results == apda_teams)評估爲True。我想知道的是爲什麼(apda_teams ==隊)也評估爲真,當apda_teams是一個球隊的副本,然後在傳遞給一個函數時被修改。現在團隊也被apda_teams傳遞給函數所改變,即使團隊永遠不會通過任何函數。 –

+0

對於延遲抱歉,apda_teams =隊(與參考相同的賦值),您需要像apda_teams = dict(隊)或列表apda_teams = list(隊)一樣執行深度拷貝。 –