Python: Как я могу изменить значения словаря в цикле for, чередуя ключи? - PullRequest
3 голосов
/ 12 марта 2011

Я новичок в Python (и в программировании).

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

#coding: utf-8
dict1 = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
dict2 = dict.fromkeys(dict1.values(),[])

for key in dict2:
    if key == 'value1':
        dict2[key].extend(['test1', 'test2'])
    elif key == 'value2':
        dict2[key].extend(['test3', 'test4'])
    elif key == 'value3':
        dict2[key].extend(['test5', 'test6'])

print (dict2['value1'])
print (dict2['value3'])

Я ожидал, что результаты будут:

 ['test5', 'test6']
 ['test1', 'test2']

, но на самом деле я получил:

 ['test5', 'test6', 'test3', 'test4', 'test1', 'test2']
 ['test5', 'test6', 'test3', 'test4', 'test1', 'test2']

Я полагаю, что проблема может быть связана с тем, что я сделал словарь из другого словаря с использованием «dict.fromkeys», но я не мог понять, почему это проблематично, даже если это так.

Спасибо за ваше внимание.Ждем ваших предложений.

Ответы [ 5 ]

6 голосов
/ 12 марта 2011

Все значения dict2 фактически являются одним и тем же экземпляром списка, поскольку передача [] в dict.fromkeys() создает только один экземпляр списка. Попробуйте

dict2 = dict((v, []) for v in dict1.values())
2 голосов
/ 12 марта 2011

Проблема в том, что вы использовали изменяемый объект в качестве инициализатора значения.Это один и тот же объект для каждого значения.

Python2> dict1 = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
Python2> dict2 = dict.fromkeys(dict1.values(),[])
Python2> dict2
{'value1': [], 'value2': [], 'value3': []}
Python2> dict2['value1']
[]
Python2> id(dict2['value1'])
43895336
Python2> id(dict2['value2'])
43895336
Python2> id(dict2['value3'])
43895336

Таким образом, вы расширяете тот же список.

0 голосов
/ 13 марта 2011

Как уже отмечали другие, проблема в том, что ваш вызов dict.fromkeys() связывает ссылку на тот же пустой список с каждым ключом, который он создает в новом словаре. Простое решение - сделать класс dict2 defaultdict из модуля collections и сделать значение по умолчанию отдельным вновь созданным пустым list:

from collections import defaultdict

dict1 = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
dict2 = defaultdict(list)

for key in dict1.itervalues():
    if key == 'value1':
        dict2[key].extend(['test1', 'test2'])
    elif key == 'value2':
        dict2[key].extend(['test3', 'test4'])
    elif key == 'value3':
        dict2[key].extend(['test5', 'test6'])

print dict2['value1']
# ['test1', 'test2']
print dict2['value3']
# ['test5', 'test6']
0 голосов
/ 12 марта 2011

Проблема в том, что dict.fromkeys() инициализирует каждый элемент одним и тем же объектом .

dict2 = dict((x, []) for x in dict1.values())
0 голосов
/ 12 марта 2011

Итерация по yourdict.keys() (это возвращает список, так что на него не будут влиять какие-либо изменения в dict)

...