[Python-Dev] Proposal: defaultdict

Walter Dörwald walter at livinglogic.de
Fri Feb 17 10:31:25 CET 2006


Guido van Rossum wrote:

> A bunch of Googlers were discussing the best way of doing the
> following (a common idiom when maintaining a dict of lists of values
> relating to a key, sometimes called a multimap):
> 
>   if key not in d: d[key] = []
>   d[key].append(value)
> 
> An alternative way to spell this uses setdefault(), but it's not very readable:
> 
>   d.setdefault(key, []).append(value)
> 
> and it also suffers from creating an unnecessary list instance.
> (Timings were inconclusive; the approaches are within 5-10% of each
> other in speed.)
> 
> My conclusion is that setdefault() is a failure -- it was a
> well-intentioned construct, but doesn't actually create more readable
> code.
> 
> Google has an internal data type called a DefaultDict which gets
> passed a default value upon construction. Its __getitem__ method,
> instead of raising KeyError, inserts a shallow copy (!) of the given
> default value into the dict when the value is not found. So the above
> code, after
> 
>   d = DefaultDict([])
> 
> can be written as simply
> 
>   d[key].append(value)

Using a shallow copy of the default seems a bit too magical to me. How 
would this be done? Via copy.copy?

And passing [] to the constructor of dict has a different meaning already.

Fetching the default via a static/class method would solve both problems:

class default_dict(dict):
    def __getitem__(self, key):
       if key in self:
          return dict.__getitem__(self, key)
       else:
          default = self.getdefault()
          self[key] = default
          return default

class multi_map(default_dict):
    @staticmethod
    def getdefault(self):
       return []

class counting_dict(default_dict):
    @staticmethod
    def getdefault(self):
       return 0

> [...]

Bye,
    Walter Dörwald


More information about the Python-Dev mailing list