带有默认值1的defaultdict?

89

我是Python的新手,从某个地方阅读了一些代码片段。它是计数排序的实现。

代码如下:

from collections import defaultdict
def sort_colors(A):
    ht = {}                        # a hash map
    ht = defaultdict(lambda:0, ht) # with default value 1
    for i in A:
         ht[i] += 1
    ret = []
    for k in [0, 1, 2]:
        ret.extend([k]*ht[k])
    return ret

就像在函数的前两行所述,它是

ht = {}
ht = defaultdict(lambda:0, ht)

我对这个初始化不是很清楚,你能帮我搞明白吗?此外,我们是否应该用以下两行代码替换它们?

ht = defaultdict(int) # default value 0

4
只要你从collections中导入,最好直接使用“Counter”。 - Kevin
3
默认值不是1,而是0。 - Matt Ball
4
尝试使用ht = defaultdict(lambda: 1) # with default value 1并删除前面的ht = {},因为前面的赋值语句没有意义,你在下一行就已经改变了ht的值。 - martineau
3个回答

138

简短回答(如下Montaro的回答)

defaultdict(lambda:1)

defaultdict的工作原理的详细解释

ht = {}
ht = defaultdict(lambda:0, ht)

defaultdictdict的不同之处在于,当您尝试访问一个不存在的键时,常规dict会引发一个KeyError异常。然而,defaultdict不会引发错误:它将为您创建该键。有哪个值?使用您作为参数传递的callable的返回值。在这种情况下,每个新键都将以值0创建(lambda:0函数的简单返回值),这也恰好是int()的相同返回值,因此在这种情况下,更改默认函数为int()不会有任何区别。

更详细地解释这行代码:ht = defaultdict(lambda:0, ht)

第一个参数是一个函数,它是一个可调用对象。这是将被调用来为一个不存在的键创建新值的函数。第二个参数ht是可选的,并且指的是新defaultdict将基于的基础字典。因此,如果ht具有一些键和值,那么defaultdict也会具有相应的键和值。如果您尝试访问这些键,则会获得旧值。 但是,如果您没有传递基本字典,那么将创建全新的defaultdict,因此,访问所有新键都会获得从可调用对象返回的默认值。(在这种情况下,由于ht最初是一个空的dict,因此进行ht = defaultdict(lambda:0)ht = defaultdict(int)ht = defaultdict(lambda:0, ht)没有任何区别:它们都将构建相同的defaultdict。)


(lambda:0, ht) 只是为了能够使用 0 调用吗? - chancyWu
没错。我编辑了这篇文章,以便更详细地分解它。 - rafaelc
谢谢你的回答。你知道如何让常量始终不同吗?我解释一下:defaultdict(lambda: 'string', ht) 不会按预期工作,因为所有新键都将共享 'string' 的相同实例。我该如何每次提供一个副本?请注意,defaultdict(lambda: copy.copy('string'), ht) 不起作用,因为 copy 只被评估一次。 - Dr_Zaszuś
@Dr_Zaszuś,很抱歉,我不认为我理解你的例子。字符串是不可变的,并且有些是内部化的,因此即使您执行x =“some string”b = copy.copy(x),您仍然可能发现x is b == True。因此,在这种情况下使用copy与否并不重要。您能再详细解释一下吗? - rafaelc
这种方法的一个挑战是生成的字典无法被pickle。你可以将其转换为普通字典(ht=dict(ht)),然后再进行操作。 - Dr Xorile

63

我认为您可以传递一个返回1的lambda函数。

from collections import defaultdict

d = defaultdict(lambda: 1)

6

与 @Montaro 的答案等价:

def a():
    return 1

d = defaultdict(a)

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