55

Is there any difference between passing int and lambda: 0 as arguments? Or between list and lambda: []?

It looks like they do the same thing:

from collections import defaultdict
dint1 = defaultdict(lambda: 0)
dint2 = defaultdict(int)
dlist1 = defaultdict(lambda: [])
dlist2 = defaultdict(list)

for ch in 'abracadabra':
    dint1[ch] += 1
    dint2[ch] += 1
    dlist1[ch].append(1)
    dlist2[ch].append(1)

print dint1.items()
print dint2.items()
print dlist1.items()
print dlist2.items()
## -- Output: --
[('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
[('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]
[('a', [1, 1, 1, 1, 1]), ('r', [1, 1]), ('b', [1, 1]), ('c', [1]), ('d', [1])]
[('a', [1, 1, 1, 1, 1]), ('r', [1, 1]), ('b', [1, 1]), ('c', [1]), ('d', [1])]

but are there any cases where they'll have different behavior, or is it merely a notational difference?

beardc
  • 20,283
  • 17
  • 76
  • 94

1 Answers1

61

All that defaultdict requires is a callable object that will return what should be used as a default value when called with no parameters.

If you were to call the int constructor, it would return 0 and if you were to call lambda: 0, it would return 0. Same with the lists. The only difference here is that the constructor will always use it's logic to create the object. A lambda, you could add additional logic if you chose to do so.

e.g.,

# alternating between `0` and `[]`
from itertools import count
factory = lambda c=count(): 0 if next(c) % 2 else []
superdict = defaultdict(factory)
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • 3
    You might also want to see this answer on thread safety: http://stackoverflow.com/questions/6319207/are-lists-thread-safe#answer-6319267 Using `int` would be thread safe, whereas using `lambda: 0` would not be. – Carl Oct 27 '15 at 05:49
  • 2
    I'm sorry but I can't see why `lambda: 0` not being thread safe based on the post referred. According the the `defaultdict` doc, the factory would be called within `dict.__getitem__()`. `dict.__getitem__()` as a whole seems to be guaranteed to be thread safe according to the post referred. Besides, the factory (either `int` or `lambda: 0`) is just something to be called somewhere. It seems that changing from one to the other, being called from anywhere, would not break thread safety, providing that neither of the two factories modify anything beyond themselves. @Carl – Mingliang Dec 22 '16 at 04:57