Python中的defaultdict: 0与int以及[]与list的区别

57

intlambda: 0 作为参数传递有区别吗?或者 listlambda: [] 之间有区别吗?

看起来它们做的事情是一样的:

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])]

但是它们是否存在行为上不同的情况,还是仅仅是符号上的区别?


1
我一直认为它们是相同的,但我期待着被纠正,所以我点了个赞 :) - Maria Zverina
1个回答

63

defaultdict只需要一个可调用对象,当不带参数地调用时,它会返回默认值。

如果你调用int构造函数,它将返回0。如果你调用lambda: 0,它也会返回0。列表也是一样的。唯一的区别在于,构造函数总是使用其逻辑创建对象。而对于lambda函数,你可以添加其他逻辑操作。

例如:

# alternating between `0` and `[]`
from itertools import count
factory = lambda c=count(): 0 if next(c) % 2 else []
superdict = defaultdict(factory)

3
您可能还希望查看有关线程安全的此答案:https://dev59.com/h2015IYBdhLWcg3w6QHA 使用“int”将是线程安全的,而使用“lambda:0”则不会。 - Carl
3
很抱歉,根据所提到的帖子,我无法理解为什么“lambda: 0”不是线程安全的。根据“defaultdict”文档,工厂将在“dict.getitem()”内部调用。根据所提到的帖子,“dict.getitem()”整体似乎保证是线程安全的。此外,工厂(无论是“int”还是“lambda: 0”)只是要在某个地方调用的东西。似乎从一个工厂更改为另一个工厂,在任何地方被调用,都不会破坏线程安全性,前提是这两个工厂都不修改除它们自己以外的任何内容。@Carl - Mingliang
我在此声明,除非有证据证明否则,两个版本(产生0)都是线程安全的。由于功能上是相同的,一个问题仍然存在:哪个更符合Python的风格? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接