每日一包 - collections.defaultdict

355 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

介绍

在Python内置的dict中获取值的方式有两种:

  • dict.get(key, key不存在时返回的值) - 当key不存在时返回指定值
  • dict[key] - 当key不存在时则抛出异常

如果我们希望当key不存在时返回一个默认值的话并且不需要手动指定该默认值时,就可以考虑使用defaultdict

defaultdictdict的子类,区别于dictdefaultdict有一个非常好用的特性,就是当key不存在时会产生一个默认值给这个key,至于这个默认值是什么我们接下来会进行详细介绍。

使用

基础介绍

collections.defaultdict(default_factory=None, **kwargs)

返回一个类似于字典的对象,第一个属性default_factory用于为不存在的key提供默认值,如果不指定(None),当key不存在时还是会抛出Keyerror

如果不为None,则会被调用为key提供一个默认值,这个值和key将会作为一组键值对写入到字典中。

需要注意的是当defaultdict使用get方法获取值时,依旧会返回None,不会返回default_factory产生的默认值。

代码示例

如下代码示例(来自官方文档),我们使用list作为default_factory,可以非常简单的将下面的序列转换成字典。

s  = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)
​
​
sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

上述代码的原理也比较简单,当每个键第一次出现时,字典中还没有该键,因此defaultdict就会自动创建该键,并且值是由default_factory产生的默认值-空列表,然后通过列表的append操作将值添加到列表中,这个方法比同效果的dict.setdefault要更加的简单和快速。

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = {}
for k, v in s:
    d.setdefault(k, []).append(v)
​
​
sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

当然我们也可以将default_factory设置为int,使用defaultdict进行计数会更加方便和快捷:

s = 'mississippi'
d = defaultdict(int)
for k in s:
    d[k] += 1
sorted(d.items())
 [('i', 4), ('m', 1), ('p', 2), ('s', 4)]

如果没有defaultdict计数的代码可能会像下面这样:

s = 'mississippi'
d = {}
for i in s:
    if i not in d:
        d[i] = 1
    else:
        d[i] += 1
print(d)

总结

defaultdict帮助你减少了出现未预期的KeyErrors的机会。减少未预期的KeyErrors意味着你可以用更少的行更清晰地编写你的程序。