Почему присвоение значений ключам в идентичных, но по-разному создаваемых вложенных словарях приводит к разным результатам? - PullRequest
2 голосов
/ 13 февраля 2020

Фрагменты кода стоят тысячу слов, поэтому вот они:

# Creation of data_dict1
data_types = ('abnormal', 'normal')
data_dict1 = dict.fromkeys(data_types, {0: {}, 1: {}})
# Creation of data_dict2
data_dict2 = data_dict2 = {'abnormal': {0: {}, 1: {}}, 'normal': {0: {}, 1: {}}}

# Check
print(data_dict1)
print(data_dict2)
print(data_dict1 == data_dict2)

>>> {'abnormal': {0: {}, 1: {}}, 'normal': {0: {}, 1: {}}}
>>> {'abnormal': {0: {}, 1: {}}, 'normal': {0: {}, 1: {}}}
>>> True

Как видите, вложенные словари data_dict1 и data_dict2 идентичны независимо от их методов создания. Но когда я присваиваю значения одним и тем же способом, я получаю разные результаты:

data_dict1['abnormal'][0]['result'] = 'abnormal_0'
data_dict1['abnormal'][1]['result'] = 'abnormal_1'
data_dict1['normal'][0]['result'] = 'normal_0'
data_dict1['normal'][1]['result'] = 'normal_1'

data_dict2['abnormal'][0]['result'] = 'abnormal_0'
data_dict2['abnormal'][1]['result'] = 'abnormal_1'
data_dict2['normal'][0]['result'] = 'normal_0'
data_dict2['normal'][1]['result'] = 'normal_1'

# Check
print(data_dict1)
print(data_dict2)
print(data_dict1 == data_dict2)

>>> {'abnormal': {0: {'result': 'normal_0'}, 1: {'result': 'normal_1'}}, 'normal': {0: {'result': 'normal_0'}, 1: {'result': 'normal_1'}}}
>>> {'abnormal': {0: {'result': 'abnormal_0'}, 1: {'result': 'abnormal_1'}}, 'normal': {0: {'result': 'normal_0'}, 1: {'result': 'normal_1'}}}
>>> False

Значения для data_dict1 ['abnormal'] [0] ['result'] и data_dict1 ['annormal'] [0] ['result'] являются 'normal_0' и 'normal_1' , соответственно, и не 'abnormal_0' и 'abnormal_1' , как и должно быть. Почему это так?

1 Ответ

3 голосов
/ 13 февраля 2020

Это происходит из-за того, как вы инициируете data_dict1.

data_dict1 = dict.fromkeys(data_types, {0: {}, 1: {}})

Когда вы делаете это, оба ключа в data_dict1 устанавливаются в один и тот же вложенный словарь. Это означает, что после этих строк:

data_dict1['abnormal'][0]['result'] = 'abnormal_0'
data_dict1['abnormal'][1]['result'] = 'abnormal_1'

Значение обоих ключей в словаре abnormal и normal изменяется. Если мы проверим data_dict1 на этом этапе, мы увидим:

>>> data_dict1
{'abnormal': {0: {'result': 'abnormal_0'}, 1: {'result': 'abnormal_1'}},
 'normal': {0: {'result': 'abnormal_0'}, 1: {'result': 'abnormal_1'}}}

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

Мы можем проверить, что оба вложенных словаря в действительности являются одним и тем же словарем в памяти, используя is:

>>> data_dict1['abnormal'] is data_dict1['normal']
True

Вы инициировали data_dict2, фактически присвоив ключи различным вложенным словарям. и мы видим, что это верно так же, как и выше:

>>> data_dict2['abnormal'] is data_dict2['normal']
False

Мы можем избежать такого поведения, не вводя его, как вы это делали в data_dict2. Один из способов сделать это - использовать словарь:

>>> data_types = ('abnormal', 'normal')
>>> data_dict1 = {k: {0: {}, 1: {}} for k in data_types}
>>> data_dict1['abnormal'] is data_dict1['normal']
False
...