2012-02-03 123 views
3

有人可以解釋我的這種行爲?奇怪的蟒蛇字典行爲

mapping = dict.fromkeys([1, 2, 3], []) 
objects = [{'pk': 1}, {'pk': 2}, {'pk': 3}] 

for obj in objects: 
    pk = obj['pk'] 
    mapping[pk].append(obj) 

print mapping 

# expected: {1: [{'pk': 1}], 2: [{'pk': 2}], 3: [{'pk': 3}]} 
# got: {1: [{'pk': 1}, {'pk': 2}, {'pk': 3}], 2: [{'pk': 1}, {'pk': 2}, {'pk': 3}], 3: [{'pk': 1}, {'pk': 2}, {'pk': 3}]} 

我試圖向類型的字典中objects映射到另一個字典的鍵是原始字典的性能。假設objects列表包含每個獨特PK的幾個對象(我不僅僅在這裏使用map)。

回答

5

這是因爲:

mapping = dict.fromkeys([1, 2, 3], []) 

[]計算一次,所以每個按鍵都有相同的列表的價值。請嘗試使用collections.defaultdict

+1

:facepalm:謝謝。 (由於某種原因,我會在8分鐘內接受答案) – Aaron 2012-02-03 09:19:41

1

如果更改mapping如下:

from collections import defaultdict 
mapping = defaultdict(list) 

,並保持休息原樣,代碼會做你的期望。

您當前的代碼的問題是mapping的所有三個鍵映射到相同的列表。當你將一個元素附加到一個元素上時,你可以將它附加到所有元素上。

1

它發生,因爲在這一行:

mapping = dict.fromkeys([1, 2, 3], []) 

你分配相同的列表,每個鍵。而且因爲列表是可變的,所以通過修改一個鍵的列表,你可以同時修改其他鍵的列表。

1

在第1行上,使用表達式[]會導致創建一個空列表。

這是上面代碼片段中唯一出現的空列表對象。當dict.fromkeys運行時,它不會創建空列表的三個不同副本。相反,它會對SAME空列表進行三次引用。

因此,在以後的循環中,每次向空列表中添加另一個數字時,它都是相同的列表。