Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the value in one key changes the values in all keys in a dictionary of sets created using fromkeys()

I am initializing a sequence like this

seq = {'a', 'b', 'c', 'd', 'e'}

Now I am using fromkeys() to convert sequence to dict of sets. here is what I am doing:

val = set()
seq_dict =  dict.fromkeys(seq, val)

Now it seems if add an element to only one of my dictionary keys set, that element is being added to all the other sets. Here is the example:

seq_dict['a'].add("val1")
print(seq_dict)
{'d': {'val1'}, 'c': {'val1'}, 'b': {'val1'}, 'a': {'val1'}, 'e': {'val1'}}

Not sure if I am using the fromkeys in a right way though?

like image 797
armin Avatar asked Sep 15 '25 08:09

armin


2 Answers

The fromkeys method is working as expected, since you have the correct result: a dictionary with keys that are the characters in seq variable, and each value that is an empty set.

Your issue is due to mutability of the value you assigned: you assigned an empty set as value for all keywords. If you change this (seq_dict['a'].add("val1")), then the values for all keywords are changed (each keyword references the original empty set).

You may want to use dictionary comprehension (which creates a new different copy of the empty set for each key) to avoid this issue:

seq = {'a', 'b', 'c', 'd', 'e'}
seq_dict = {key: set() for key in seq}
like image 71
mattiatantardini Avatar answered Sep 17 '25 22:09

mattiatantardini


val = set()
seq_dict =  dict.fromkeys(seq, val)

You are initializing the seq_dict with the same set (a mutable type), so editing seq_dict['a'] you are editing the same set which is the value of all the other keys.


If you don't want this to happen, you'll have to initialize the dictionary in an other way.

>>> d = {i: set() for i in ('a', 'b', 'c', 'd', 'e')}
>>> d
{'a': set(), 'b': set(), 'c': set(), 'd': set(), 'e': set()}
>>> d['a']
set()
>>> d['a'].add('ehi')
>>> d
{'a': {'ehi'}, 'b': set(), 'c': set(), 'd': set(), 'e': set()}

So, in other words, you have to "isolate" the **immutable**s parts of the set:

seq = {'a', 'b', 'c', 'd', 'e'}
seq_dict = {key: set() for key in seq}
like image 23
FLAK-ZOSO Avatar answered Sep 17 '25 21:09

FLAK-ZOSO