73

I know you can use setdefault(key, value) to set default value for a given key, but is there a way to set default values of all keys to some value after creating a dict ?

Put it another way, I want the dict to return the specified default value for every key I didn't yet set.

Derrick Zhang
  • 21,201
  • 18
  • 53
  • 73
  • 1
    What's this set of "all keys" you are talking about? There's an infinite amount of potential keys, even if you restrict yourself to e.g. strings. Could you give an example? –  Feb 04 '12 at 09:44
  • you can use get method, `a.get(k[, x]) a[k] if k in a, else x` – Anycorn Feb 04 '12 at 09:46
  • Some help in the inverse direction: http://stackoverflow.com/questions/7688453/how-to-fix-default-values-from-a-dictionary-pythonically – Jesvin Jose Feb 04 '12 at 10:27
  • 1
    @delnan What I want is to get a default value for every key I didn't set yet. – Derrick Zhang Feb 04 '12 at 12:20
  • Too lengthy to post here, I describe solutions in this research blog post: https://persagen.com/2020/03/05/python_dictionaries_default_values_immutable_keys.html – Victoria Stuart Mar 06 '20 at 03:04

7 Answers7

132

You can replace your old dictionary with a defaultdict:

>>> from collections import defaultdict
>>> d = {'foo': 123, 'bar': 456}
>>> d['baz']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'baz'
>>> d = defaultdict(lambda: -1, d)
>>> d['baz']
-1

The "trick" here is that a defaultdict can be initialized with another dict. This means that you preserve the existing values in your normal dict:

>>> d['foo']
123
Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
  • 1
    Is there any way to get this working with `get` and similar methods or constructs like `in`? – 0xc0de Dec 17 '15 at 09:55
  • 1
    Isn't just `defaultdict(lambda: -1)` enough? what is the `d` for? – yiwei Feb 02 '16 at 03:20
  • 3
    @yiwei It is there to initialize the `defaultdict` with the values from the existing `dict`. The question said "I want the dict to return the specified default value for every key I didn't yet set." and the way to do this is to create a `defaultdict` initialized with the old `dict`. – Martin Geisler Feb 03 '16 at 09:08
13

Use defaultdict

from collections import defaultdict
a = {} 
a = defaultdict(lambda:0,a)
a["anything"] # => 0

This is very useful for case like this,where default values for every key is set as 0:

results ={ 'pre-access' : {'count': 4, 'pass_count': 2},'no-access' : {'count': 55, 'pass_count': 19}
for k,v in results.iteritems():
  a['count'] += v['count']
  a['pass_count'] += v['pass_count']
Abhaya
  • 2,086
  • 16
  • 21
7

In case you actually mean what you seem to ask, I'll provide this alternative answer.

You say you want the dict to return a specified value, you do not say you want to set that value at the same time, like defaultdict does. This will do so:

class DictWithDefault(dict):
    def __init__(self, default, **kwargs):
        self.default = default
        super(DictWithDefault, self).__init__(**kwargs)

    def __getitem__(self, key):
        if key in self:
            return super(DictWithDefault, self).__getitem__(key)
        return self.default

Use like this:

d = DictWIthDefault(99, x=5, y=3)
print d["x"]   # 5
print d[42]    # 99
42 in d        # False
d[42] = 3
42 in d        # True

Alternatively, you can use a standard dict like this:

d = {3: 9, 4: 2}
default = 99
print d.get(3, default)  # 9
print d.get(42, default) # 99
Lauritz V. Thaulow
  • 49,139
  • 12
  • 73
  • 92
6

defaultdict can do something like that for you.

Example:

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d
defaultdict(<class 'list'>, {})
>>> d['new'].append(10)
>>> d
defaultdict(<class 'list'>, {'new': [10]})
Rik Poggi
  • 28,332
  • 6
  • 65
  • 82
2

Is this what you want:

>>> d={'a':1,'b':2,'c':3}
>>> default_val=99
>>> for k in d:
...     d[k]=default_val
...     
>>> d
{'a': 99, 'b': 99, 'c': 99}
>>> 

>>> d={'a':1,'b':2,'c':3}
>>> from collections import defaultdict
>>> d=defaultdict(lambda:99,d)
>>> d
defaultdict(<function <lambda> at 0x03D21630>, {'a': 1, 'c': 3, 'b': 2})
>>> d[3]
99
Rusty Rob
  • 16,489
  • 8
  • 100
  • 116
1

You can use the following class. Just change zero to any default value you like. The solution was tested in Python 2.7.

class cDefaultDict(dict):
    # dictionary that returns zero for missing keys
    # keys with zero values are not stored

    def __missing__(self,key):
        return 0

    def __setitem__(self, key, value):
        if value==0:
            if key in self:  # returns zero anyway, so no need to store it
                del self[key]
        else:
            dict.__setitem__(self, key, value)
Apogentus
  • 6,371
  • 6
  • 32
  • 33
1

Not after creating it, no. But you could use a defaultdict in the first place, which sets default values when you initialize it.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895