2016-11-07 52 views
0

爲什麼代碼中的這個小改動會使此代碼的工作方式不同。我只是在學習Python。誰能以簡單的方式解釋? 編輯: 我沒有意識到追加到列表字典是指向相同的字典,而不是它的實際副本。我在這篇文章之前試圖找到解決方案,但可能表達我的問題有點不同,這可能會導致有經驗的程序員將其視爲重複。嵌套字典已更改我不明白爲什麼

輸入

# Make an empty list for storing aliens. 
aliens = [] 
# Make 30 green aliens. 
for alien_number in range(30): 
    new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} 
    aliens.append(new_alien) 

for alien in aliens[0:3]: 
    if alien['color'] == 'green': 
     alien['color'] = 'yellow' 
     alien['speed'] = 'medium' 
     alien['points'] = 10 
# Show the first 5 aliens: 
for alien in aliens[:5]: 
    print(alien) 
print("...") 
# Show how many aliens have been created. 
print("Total number of aliens: " + str(len(aliens))) 

輸出

{'points': 10, 'color': 'yellow', 'speed': 'medium'} 
{'points': 10, 'color': 'yellow', 'speed': 'medium'} 
{'points': 10, 'color': 'yellow', 'speed': 'medium'} 
{'points': 5, 'color': 'green', 'speed': 'slow'} 
{'points': 5, 'color': 'green', 'speed': 'slow'} 
... 
Total number of aliens: 30 

現在改變了代碼,我會初始化字典中的第一個外for循環

輸入

# Make an empty list for storing aliens. 
aliens = [] 
# HERE IS THE CHANGE 
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} 
# Make 30 green aliens. 
for alien_number in range(30): 
    aliens.append(new_alien) 

for alien in aliens[0:3]: 
    if alien['color'] == 'green': 
     alien['color'] = 'yellow' 
     alien['speed'] = 'medium' 
     alien['points'] = 10 
# Show the first 5 aliens: 
for alien in aliens[:5]: 
    print(alien) 
print("...") 
# Show how many aliens have been created. 
print("Total number of aliens: " + str(len(aliens))) 

輸出

{'color': 'yellow', 'points': 10, 'speed': 'medium'} 
{'color': 'yellow', 'points': 10, 'speed': 'medium'} 
{'color': 'yellow', 'points': 10, 'speed': 'medium'} 
{'color': 'yellow', 'points': 10, 'speed': 'medium'} 
{'color': 'yellow', 'points': 10, 'speed': 'medium'} 
... 
Total number of aliens: 30 

爲什麼在第二個是整個字典改變,而不只是前3個詞典?

+5

之前,您每次都通過循環創建一個新字典。現在,您只能創建一個字典,並將其添加到同一個列表中30次。使用列表中的哪個索引並不重要,它仍指向相同的字典。 –

+0

@BrendanAbel是正確的 - 與其他語言不同,Python中的'='*從不*做任何東西的副本。 '{'color':'green','points':5,'speed':'slow'}'表達式會創建一個新的'dict',並且在您的原始代碼中運行這個30次,但在第二次只運行一次。 –

+0

Ahh geez現在我明白了@Brendan ......謝謝...閱讀您的評論3 *更多。我今天有點慢。非常感謝你解釋它;) – martin

回答

0

與您的代碼的一點是,當您構建第一個字典時,它會創建它並在new_alien變量中存儲對它的引用。請注意,這不是對象本身,而是對象的引用。 在第一個片段中,您每次都創建一個新字典,並在aliens列表中附加對新字典的引用。在第二種情況下,您只創建一個字典,並將引用添加到該列表五次。 這解釋了爲什麼在第二種情況下,您實際上是在修改相同的字典。讓我們來看看這個例子:

dct = {'a': 10, 'b': 20} # in this moment the dictionary is initialised and a reference to it is stored in the variable dct (let's call this reference 0x01) 
# dct = 0x01 
lst = [] 
for i in range(5): 
    lst.append(dct) 
# at the end of the loop lst = [0x01, 0x01, 0x01, 0x01, 0x01] 
lst[0]['a'] = 20 # this means take lst[0] (which is 0x01) interpret it as a dictionary and change the value at `'a'` to 20 

所以這個變化會影響您已創建唯一的字典,這是dct。 在你的第一個片段,而是你創造5個不同的字典的情況下,並修改的只是其中的一部分,看看這個例子:

lst = [] 
for i in range(5): 
    new_dict = {'a': 10, 'b': 20} 
    lst.append(new_dict) 
# by the end of the loop, lst will have references to five different dictionaries, for instance lst = [0x01, 0x02, 0x03, 0x04, 0x05] 

所以在這種情況下,修改一個條目不會影響他人

+0

謝謝你的解釋。 – martin