miyazaki_tara
miyazaki_tara

Reputation: 357

Python: How can I modify dictionary values in a for loop alternating the keys?

I am new to Python (and to programming).

I'd like to modify a dictionary in a for loop by alternating the key of the dictionary. I wrote the following code, which was unsccessful, however:

#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'])

I expected the results to be:

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

but I actually got:

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

I guess the problem might come from my making the dictionary from another dictionary using "dict.fromkeys", but I couldn't see why it is problematic even if it is the case.

Thanks for your attention. Looking forward to your suggestions.

Upvotes: 4

Views: 4680

Answers (5)

Sven Marnach
Sven Marnach

Reputation: 601649

All values of dict2 are actually the same list instance, since passing [] to dict.fromkeys() only creates one list instance. Try

dict2 = {v: [] for v in dict1.values()}

Upvotes: 7

martineau
martineau

Reputation: 123463

As others have pointed-out, the problem is that your call to dict.fromkeys() associates a reference to the same empty list with each key it creates in the new dictionary. An easy solution is to make dict2 a defaultdict class from the collections module and make the default value a separate newly created empty 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']

Upvotes: 0

Keith
Keith

Reputation: 43024

The problem is you used a mutable object as the value initializer. It is the very same object for each value.

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

So you are extending the same list.

Upvotes: 2

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798676

The problem is that dict.fromkeys() initializes each item with the same object.

dict2 = dict((x, []) for x in dict1.values())

Upvotes: 0

ThiefMaster
ThiefMaster

Reputation: 318508

Iterate over yourdict.keys() (this returns a list so it will not be affected by any change to the dict)

Upvotes: 0

Related Questions