4

I tried using dict.fromkeys([1,2,3],set()). This initializes creates the dictionary but when I add a value to any one of the sets all the sets get updated!

>>> d=dict.fromkeys([1,2,3],set())
>>> d
>>> {1: set(), 2: set(), 3: set()}
>>> d[1].add('a')
>>> d
>>> {1: {'a'}, 2: {'a'}, 3: {'a'}}

It seems that all the three values of the dictionary are referring to the same set. I want to initialize all the values of the dictionary to empty sets so that I can perform some operations on these sets in a loop based on the keys later.

  • See also `defaultdict` - you can create a dict that will automatically create an empty set for you for each new key. – Kos Mar 19 '18 at 08:59
  • Possible duplicate of [How do I initialize a dictionary of empty lists in Python?](https://stackoverflow.com/questions/11509721/how-do-i-initialize-a-dictionary-of-empty-lists-in-python) – Joseph Sible-Reinstate Monica Sep 29 '19 at 01:57

3 Answers3

10

Using dictionary comprehension

d = {x: set() for x in [1, 2, 3]}

Or using collections.defaultdict

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • Great! That works. But I thought the `fromkeys()` should be doing the same thing. Can you explain whats going on in the case of `fromkeys()`. – Zanylytical Scientist Mar 19 '18 at 09:00
  • `set()` is only invoked *once* in the `fromkeys()` call. The DC calls it *each time*. – Ignacio Vazquez-Abrams Mar 19 '18 at 09:01
  • Then I don't see the point of `fromkeys()` function other than maybe using it for the case where the initializing value is an atomic type like numeral or None. – Zanylytical Scientist Mar 19 '18 at 09:05
  • @Dhruv Precisely, if you want to have mutable values you usually use a `defaultdict` which saves you the trouble of initializing in the first place, or a dict comprehension if initialization is important in itself or depends on the keys. – phihag Mar 19 '18 at 09:11
2

You can use collections.defaultdict

>>> from collections import defaultdict
>>> d = defaultdict(set)
>>> d[1].add('a')
>>> d
defaultdict(<class 'set'>, {1: {'a'}})
>>> d[2].add('b')
>>> d
defaultdict(<class 'set'>, {1: {'a'}, 2: {'b'}})

The way it works, is, when you try to add a value to a key like dict[key].add(value), it checks whether the key is present; if so, then it adds the value to the set. If it is not present the value is added as a set since the default is set as a set (defaultdict(set)).

Keyur Potdar
  • 7,158
  • 6
  • 25
  • 40
1

You want a defaultdict so you don't need to initialize the sets in the first place:

>>> from collections import defaultdict
>>> d = defaultdict(set)
# That's it, initialization complete. Use goes like this:
>>> d[1].add('a')
>>> d[2].add('b')
>>> d[3].add('c')
>>> d
defaultdict(<class 'set'>, {1: {'a'}, 2: {'b'}, 3: {'c'}})
phihag
  • 278,196
  • 72
  • 453
  • 469