2012-02-03 4 views
3

Может ли кто-нибудь объяснить это поведение для меня?Странное поведение python dict

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}]} 

Я пытаюсь сопоставить dicts в objects другой Словарь, ключи которого является свойством исходного Dict. Предположим, что список objects содержит несколько объектов каждого уникального ПК (причина, по которой я не просто использую map здесь).

ответ

5

Это потому, что в:

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

[] вычисляется один раз, так что каждый ключ имеет тот же список в качестве значения. Вместо этого попробуйте использовать collections.defaultdict.

+1

: facepalm: Спасибо. (Я буду принимать ответ ровно через 8 минут по какой-то причине) – Aaron

1

При изменении mapping следующим образом:

from collections import defaultdict 
mapping = defaultdict(list) 

и держать остальное как есть, код будет делать то, что вы ожидаете.

Проблема с вашим текущим кодом заключается в том, что все три клавиши от mapping соответствуют одному и тому же списку. Когда вы добавляете элемент в один, вы фактически добавляете его ко всем.

1

Это происходит потому, что в этой строке:

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

присвоить один и тот же список каждому ключу. И поскольку списки изменяемы, путем изменения списка для одного ключа, вы одновременно изменяете список для других ключей.

1

В строке 1 использование выражения [] вызывает создание пустого списка.

Это единственный пустой объект списка, который отображается в приведенном выше фрагменте. Когда dict.fromkeys запускается, он НЕ делает три разных копии пустого списка. Вместо этого он делает три ссылки на SAME пустой список.

Таким образом, во время цикла каждый раз, когда вы добавляете еще один номер в пустой список, это тот же список.

Смежные вопросы