Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a defaultdict with a default of zero (0) [duplicate]

Similarly to this question I'd like to create a collections.defaultdict with a default value of zero for counting elements of a list of tuples:

tuples = [('foo', 5), ('foo', 5), ('bar', -5), ('bar', -2)]
totals = defaultdict(0)
for t in tuples:
    totals[t[0]] += t[1]

But defaultdict(0) says:

TypeError: first argument must be callable

How am I supposed to create a "callable" zero?

like image 513
LondonRob Avatar asked Aug 05 '15 17:08

LondonRob


People also ask

What is the default value in Defaultdict?

A defaultdict works exactly like a normal dict, but it is initialized with a function (“default factory”) that takes no arguments and provides the default value for a nonexistent key. A defaultdict will never raise a KeyError. Any key that does not exist gets the value returned by the default factory.

How do you declare a Defaultdict?

A defaultdict can be created by giving its declaration an argument that can have three values; list, set or int. According to the specified data type, the dictionary is created and when any key, that does not exist in the defaultdict is added or accessed, it is assigned a default value as opposed to giving a KeyError .

How does Defaultdict work Defaultdict stores a copy of a dictionary?

Defaultdict is a sub-class of the dictionary class that returns a dictionary-like object. The functionality of both dictionaries and defaultdict are almost same except for the fact that defaultdict never raises a KeyError. It provides a default value for the key that does not exists.

What is Lambda Defaultdict?

defaultdict takes a zero-argument callable to its constructor, which is called when the key is not found, as you correctly explained. lambda: 0 will of course always return zero, but the preferred method to do that is defaultdict(int) , which will do the same thing.


1 Answers

The docstring for collections.defaultdict is pretty confusing at first read:

defaultdict(default_factory[, ...]) --> dict with default factory

The default factory is called without arguments to produce a new value when a key is not present, in getitem only. A defaultdict compares equal to a dict with the same items. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.

All this is trying to say is that the default "value" has to be a function, and that that function will be called without arguments whenever it's needed (i.e. whenever a normal dict would raise a KeyError.) The docstring refers to this function as default_factory.

The bit with [, ...] says that you can optionally pass in an object (or keywords) to use as the defaultdict's initial dictionary. Thus:

In [26]: x = defaultdict(lambda: 0, a=1, b=2)

In [28]: dict(x)
Out[28]: {'a': 1, 'b': 2}

In [29]: x['c'] # This would normally raise a `KeyError`
Out[29]: 0

In [30]: dict(x) # But here it just adds a new key!
Out[30]: {'a': 1, 'b': 2, 'c': 0}

Any function which returns zero when called with no arguments can be used:

In [31]: int()
Out[31]: 0

Thus, as per the counting example from the docs you could create a defaultdict with a default value of zero with:

defaultdict(int)
like image 82
LondonRob Avatar answered Sep 20 '22 11:09

LondonRob