Инициализировать диктант пустых списков - PullRequest
0 голосов
/ 30 апреля 2020

Я пытаюсь инициализировать диктовку пустых списков, чтобы добавить к ним, однако это привело к некоторому странному поведению:

def solution(A):
    d = dict.fromkeys(set(A), [])
    for i in range(len(A)):
        d[A[i]].append(i)
    print(d)

input:

[3, 4, 3, 2, 3, -1, 3, 3]

output :

{2: [0, 1, 2, 3, 4, 5, 6, 7],
 3: [0, 1, 2, 3, 4, 5, 6, 7],
 4: [0, 1, 2, 3, 4, 5, 6, 7],
-1: [0, 1, 2, 3, 4, 5, 6, 7]}

dict.fromkeys, кажется, инициализирует все списки как указатель на один и тот же список под колпаком, это то, что происходит? Как я могу знать, что это было бы поведение / почему это было бы поведение? Есть ли способ сказать переводчику не делать этого?

Ответы [ 3 ]

1 голос
/ 30 апреля 2020

Как я могу знать, что такое поведение будет

В документации Python говорится об этом и предупреждает вас:

classmethod fromkeys ( iterable [, value ])

Создать новый словарь с ключами из iterable и значениями, установленными на value .

fromkeys() - это метод класса, который возвращает новый словарь. значение по умолчанию None. Все значения относятся только к одному экземпляру, поэтому обычно не имеет смысла для значение быть изменяемым объектом, таким как пустой список . Чтобы получить разные значения, используйте вместо этого понимание слова.

1 голос
/ 30 апреля 2020

Все ваши списки являются одним и тем же объектом. [] - это буквальное выражение, которое оценивается перед передачей в dict.fromkeys. Как функция может знать, как дублировать любой случайный объект?

Если вы хотите такое поведение, выберите collections.defaultdict:

from collections import defaultdict

def solution(A):
    d = defaultdict(list)  # `list` is a factory funtion that can be called repeatedly
    for i in range(len(A)):
        d[A[i]].append(i)
    print(d)
    # or, if you dislike the output (note, it is a dict already)
    # print(dict(d))
0 голосов
/ 30 апреля 2020

В ключах from, если предоставленное значение является изменяемым (например, список), каждое значение ключа будет ссылкой на один и тот же объект, следовательно, все значения обновляются одновременно. Вы можете проверить это, добавив к исходному списку, чтобы получить тот же результат, что и вы:

def solution(A):
    lst = []
    d = dict.fromkeys(set(A), lst)
    for i in range(len(A)):
        lst.append(i)
    print(d)

Помимо других предоставленных ответов, вы могли бы go путь понимания словаря:

def solution(A):
    d = { key : [] for key in A }
    for i in range(len(A)):
        d[A[i]].append(i)
    print(d)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...