3

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?

martineau
  • 119,623
  • 25
  • 170
  • 301
armin
  • 591
  • 3
  • 10
  • 3
    You’ve assigned the same set to all keys. If that wasn’t the intention, use a dict comprehension to initialize the dict. –  Apr 25 '22 at 19:57
  • 2
    Similar, but not an exact duplicate: [Changing one dict value changes all values](https://stackoverflow.com/q/13498453/843953) – Pranav Hosangadi Apr 25 '22 at 19:58
  • @enke True that was not my intention. Would it be possible to give me an example? Thanks! – armin Apr 25 '22 at 20:03
  • Here's documentation on a "[set comprehension](https://docs.python.org/3/tutorial/datastructures.html#sets)" which is the way to fix the problem — and very similar to a [list comprehension](https://docs.python.org/3/tutorial/datastructures.html#tut-listcomps) so I am going to close your question as a dup. It also means you can't use the `fromkeys()` method. – martineau Apr 25 '22 at 20:44

2 Answers2

4

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}
mattiatantardini
  • 525
  • 1
  • 5
  • 23
1
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}
FLAK-ZOSO
  • 3,873
  • 4
  • 8
  • 28