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 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com