Python: Почему функция возвращает словарь, в котором все значения заполнены присваиванием? - PullRequest
0 голосов
/ 14 октября 2018

У меня есть функция, которая берет список и выводит словарь.Я создаю словарь внутри цикла и назначаю значения словаря внутри функции.Ниже приведена упрощенная версия того, что я хочу спросить:

import numpy as np

def get_myDict(tmp_list):
    my_dict = dict.fromkeys(tmp_list, 
                            dict.fromkeys([i**2 for i in tmp_list],0))
    for i in tmp_list:
        my_list = [j for j in np.arange(i)]
        my_dict[i][i**2] = sum(my_list[:]) + i
    return my_dict 

Вывод из этого выглядит следующим образом:

[In 1]: get_myDict([1,2,3,4])
[Out 1]: {1: {1: 1, 4: 3, 9: 6, 16: 10},
          2: {1: 1, 4: 3, 9: 6, 16: 10},
          3: {1: 1, 4: 3, 9: 6, 16: 10},
          4: {1: 1, 4: 3, 9: 6, 16: 10}}

В то время как я ожидаю, что вывод будет

{1: {1: 1, 4: 0, 9: 0, 16: 0},
 2: {1: 0, 4: 3, 9: 0, 16: 0},
 3: {1: 0, 4: 0, 9: 6, 16: 0},
 4: {1: 0, 4: 0, 9: 0, 16: 10}}

Я получу желаемый результат, если определю my_dict внутри функции следующим образом:

my_dict = {1: {16: 0, 1: 0, 4: 0, 9: 0}, 
           2: {16: 0, 1: 0, 4: 0, 9: 0}, 
           3: {16: 0, 1: 0, 4: 0, 9: 0}, 
           4: {16: 0, 1: 0, 4: 0, 9: 0}}

Я считаю, что это каким-то образом связано с общими ссылками.Может кто-нибудь объяснить, что я здесь делаю не так?

Ответы [ 2 ]

0 голосов
/ 14 октября 2018

Причина в том, что вы фактически передаете одно значение методу dict.fromkeys().Чтобы проиллюстрировать, что вы делаете:

import numpy as np

def get_myDict(tmp_list):
    value = dict.fromkeys([i**2 for i in tmp_list], 0)
    my_dict = dict.fromkeys(tmp_list, value)
    ...

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

Возможно, collection.defaultdict будет более удобным здесь?

0 голосов
/ 14 октября 2018

Вы правы, вы на самом деле создаете один словарь с квадратичными ключами и ссылаетесь на него несколько раз.

Используйте точное толкование (начиная с Python 2.7):

my_dict = {k: {k2: 0 for k2 in [i**2 for i in tmp_list]} for k in tmp_list}

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