[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