Странное поведение python dict - PullRequest
       3

Странное поведение python dict

3 голосов
/ 03 февраля 2012

Может кто-нибудь объяснить мне это поведение?

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 здесь).

Ответы [ 4 ]

5 голосов
/ 03 февраля 2012

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

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

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

1 голос
/ 03 февраля 2012

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

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

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

1 голос
/ 03 февраля 2012

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

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

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

1 голос
/ 03 февраля 2012

Если вы измените mapping следующим образом:

from collections import defaultdict
mapping = defaultdict(list)

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...