Search code examples
pythonpython-2.7dictionarydefaultdefault-value

Python dictionary with default key


I am running Python 2.7.10.

I would like to have a dictionary return the value stored at a particular key in case of missing item. For example, something like that:

myD = dict(...)
return myD[key] if key in myD else myD[defaultKey]

Just to make sure it is clear, I want to call myD[key] and have the right value returned without the extra if...else in my code...

This isn't quite what defaultdict does (since it takes a function to call as a default) and not quite what dict.setdefault() does, and myD.get(key, ???) does not seem to help either. I probably should inherit from dict or defaultdict and overload __init__() and missing() methods, but I could not come up with a good way to do this.


Solution

  • I'm not completely sure what you want (didn't read all the comments under your question), but think this may be at least close to what you want.

    class DefaultKeyDict(dict):
        def __init__(self, default_key, *args, **kwargs):
            self.default_key = default_key
            super(DefaultKeyDict, self).__init__(*args, **kwargs)
    
        def __missing__ (self, key):
            if self.default_key not in self:  # default key not defined
                raise KeyError(key)
            return self[self.default_key]
    
        def __repr__(self):
            return ('{}({!r}, {})'.format(self.__class__.__name__,
                                          self.default_key,
                                          super(DefaultKeyDict, self).__repr__()))
    
        def __reduce__(self):  # optional, for pickle support
            args = (self.default_key if self.default_key in self else None,)
            return self.__class__, args, None, None, self.iteritems()
    
    dkdict = DefaultKeyDict('b', {'a': 1, 'b': 2, 'c': 3})
    
    print dkdict['a']  # -> 1
    print dkdict['b']  # -> 2
    print dkdict['c']  # -> 3
    print dkdict['d']  # -> 2 (value of the default key)
    
    del dkdict['b']  # delete the default key
    try:
        print dkdict['d']  # should now raise exception like normal
    except KeyError:
        print("dkdict['d'] raised a KeyError")
    

    You might want to modify the class __init__() method to accept both the default key and its value as arguments (instead of just the key).