Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can defaultdict accept callables dependent on the given missing key?

The examples given in the docs all seem to be the cases where the first callable argument in defaultdict is a "constant" function, like int, list, or lambda: const etc. I don't know if defaultdict is just supposed to take constant functions as its callabe argument, but if not, I want the callable to be dependent on the missing key values I give. For example

toy = collections.defaultdict(lambda x: len(x), {'foo': 3})
toy['barr']

What I expect is whenever I give a missing key string, for example 'barr', the container can create a new entry with 'barr' being the key and its length 4 being the value. But it doesn't work. Instead, it gives me the following error:

TypeError: <lambda>() missing 1 required positional argument: 'x'

I expected 'barr' to be this lambda's argument here, but it was apparently not the case. So what could have gone wrong?

like image 672
Vim Avatar asked Apr 07 '17 01:04

Vim


1 Answers

The default factory is never given any arguments, so you can't do it like that. What you can do, though, is subclass defaultdict and define the __missing__ method:

class CustomDefaultDict(collections.defaultdict):
    def __missing__(self, key):
        self[key] = value = len(key)
        return value

To make it more easily-extendible, you could also take advantage of the default_factory, but give it the key as an argument:

class CustomDefaultDict(collections.defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError((key,))
        self[key] = value = self.default_factory(key)
        return value
like image 120
zondo Avatar answered Sep 19 '22 23:09

zondo