[Python-Dev] Proposal: defaultdict

Adam Olsen rhamph at gmail.com
Fri Feb 17 22:54:08 CET 2006


On 2/17/06, Guido van Rossum <guido at python.org> wrote:
> - There's a fundamental difference between associating the default
> value with the dict object, and associating it with the call. So
> proposals to invent a better name/signature for setdefault() don't
> compete.

That's a feature, not a bug. :)  See below.


> - The inconsistency introduced by __getitem__() returning a value for
> keys while get(), __contains__(), and keys() etc. don't show it,
> cannot be resolved usefully. You'll just have to live with it.
> Modifying get() to do the same thing as __getitem__() doesn't seem
> useful -- it just takes away a potentially useful operation.

Again, see below.


> So here's a new proposal.
>
> Let's add a generic missing-key handling method to the dict class, as
> well as a default_factory slot initialized to None. The implementation
> is like this (but in C):
>
> def on_missing(self, key):
>   if self.default_factory is not None:
>     value = self.default_factory()
>     self[key] = value
>     return value
>   raise KeyError(key)
>
> When __getitem__() (and *only* __getitem__()) finds that the requested
> key is not present in the dict, it calls self.on_missing(key) and
> returns whatever it returns -- or raises whatever it raises.
> __getitem__() doesn't need to raise KeyError any more, that's done by
> on_missing().

Still -1.  It's better, but it violates the principle of encapsulation
by mixing how-you-use-it state with what-it-stores state.  In doing
that it has the potential to break an API documented as accepting a
dict.  Code that expects d[key] to raise an exception (and catches the
resulting KeyError) will now silently "succeed".  I believe that
necessitates a PEP to document it.

It's also makes it harder to read code.  You may expect d[key] to
raise an exception, but it won't because of a single line up several
pages (or in another file entierly!)

d.getorset(key, func) has no such problems and has a much simpler specification:

def getorset(self, key, func):
  try:
    return self[key]
  except KeyError:
    value = self[key] = func()
    return value

--
Adam Olsen, aka Rhamphoryncus


More information about the Python-Dev mailing list