Question about defaultdict

Chris Angelico rosuav at gmail.com
Sat Feb 23 11:29:19 CET 2013


On Sat, Feb 23, 2013 at 9:13 PM, Frank Millman <frank at chagford.com> wrote:
> I thought I could replace this with -
>
> from collections import defaultdict
> my_cache = defaultdict(fetch_object)
> my_obj = my_cache['a']
>
> It does not work, because fetch_object() is called without any arguments.

A reasonable thing to ask for, but not supported by the default
defaultdict. However, the key to defaultdict is the __missing__
method, and you can simply subclass dict and provide that method:

class cache(dict):
    def __missing__(self,key):
        val=fetch_object(key)
        self[key]=val
        return val

Alternatively, if you want to pass fetch_object as a parameter,
subclass defaultdict:

>>> class parameterizing_defaultdict(collections.defaultdict):
	def __missing__(self,key):
		value=self.default_factory(key)
		self[key]=value
		return value

>>> my_cache=parameterizing_defaultdict(fetch_object)
>>> my_cache["a"]
Expensive operation involving a
1
>>> my_cache["a"]
1
>>> my_cache["a"]
1
>>> my_cache["ab"]
Expensive operation involving ab
2
>>> my_cache["abc"]
Expensive operation involving abc
3

defaultdict does do some other work, but unless you need it, I'd be
inclined to go with just subclassing dict directly; in fact, it may
make sense to just in-line the fetch_object code right there in the
class.

There are several ways to go about it; you know your project better
than anyone else does!

ChrisA



More information about the Python-list mailing list