在一个需求中意外的发现了defaultdict这个东西,python中的dict很好理解,可是有一个使用起来不方便的地方在于,需要进行初始值是否初始化的判断:

list = ["aaa", "bbb", "ccc", "aaa"]
kv = {}
for d in list:
    if d in kv:
        kv[d] += 1
    else:
        kv[d] = 1

print(kv)
# {"aaa": 2, "bbb": 1, "ccc": 1}

print(kv["test"])
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#KeyError: 'test'

对于python来说,这很不酷,所以,defaultdict这个东西就出现了,上面的代码,可以改为:

from collections import defaultdict


list = ["aaa", "bbb", "ccc", "aaa"]
kv = defaultdict(int)
for d in list:
    kv[d] += 1

print(kv)
# {"aaa": 2, "bbb": 1, "ccc": 1}

print(kv["test"])
# 0

print(kv)
# {"aaa": 2, "bbb": 1, "ccc": 1, "test": 0}

也就是说,defaultdict能自动将没有创建的值,使用传入的函数来初始化,比如传入list,就能直接创建列表,使用的时候可以直接append。

除了这些基础用法,还有更加hack的用法,比如如下这个需求:
为对象进行编号,如果某几个属性相同,那么编为同一组。
这并不是一个多复杂的需求,只是用defaultdict来实现,会显得比其他方法优雅很多:

from collections import defaultdict
from itertools import count


group_value = defaultdict(count().__next__)
group_value_list = [group_value[(o.p1, o.p2, o.p3)] for o in object_list]

使用了count的next方法,在往group_value设置值的时候,会自动生成一个值,当key相同的时候,值是相同的,当key不同的时候,自动将数字增加1,当做值,这样,就能生成一个分组的列表了。

defaultdict增强了原dict的功能,并且如果创造力足够,会让程序更加优雅。

分类: 语言

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注