说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 内置 collections 模块的 defaultdict 默认值字典类型是普通字典的子类,提供了一个工厂函数,为字典查询提供一个默认值。普通字典以 key 和 value 对的形式存储数据,在获取数据时以 key 对索引,但是遇到没有的 key 会报错,这时候 defaultdict 就解决了这个问题。
defaultdict 是 Python 内置 dict 类的一个子类,第一个参数为 default_factory 工厂方法提供初始值。它的其他功能与 dict 相同,但会为一个不存在的键提供默认值,从而避免 KeyError 异常。一般用类型名称作为初始化函数参数:
from collections import defaultdict
dd = defaultdict(list)
dd['a'] = 1
dd['b'] = 2
# 还可以用
defaultdict(list, {'a': 1, 'b': 2})
defaultdict(list, a=1, b=2)
defaultdict(lambda: [], a=1, b=2) # 自定义
dd
# defaultdict(list, {'a': 1, 'b': 2})
dd['g']
# []
d['h'] += [1]
from collections import defaultdict
my_defaultdict = defaultdict(int) # 当访问不存在的键时,默认值为 0
my_defaultdict['key1'] += 1 # 即使 'key1' 原先不存在,也能正常操作
print(my_defaultdict)
# defaultdict(<class 'int'>, {'key1': 1})
my_defaultdict = defaultdict(list)
my_defaultdict['key2'].append(1) # 不会报错,自动创建空列表并添加元素
print(my_defaultdict)
# defaultdict(<class 'list'>, {'key2': [1]})
这个参数可以是 int、str、list、set 等,当字典的 key 不存在时,返回的是工厂函数的默认值,对应地:
总之参数必须是一个 callable(可调用的)或者 None,甚至是 defaultdict 自己,返回的是 defaultdict(None, {})
。这相当于 Java 中的泛型。
参数 default_factory 方法它会在不接收任何参数的情况下被调用,来为给定的键提供默认值,这个值会被添加进字典并被返回。就是说要用可调用函数作为初始化函数参数,那么这个函数不用指定任何必须的参数有返回值。这就意味着使用 lambda 时不能有参数。
给定默认值的类型之后并不意味着字典中所有值都必须是此类型,也可以是其他类型,并可对此类型执行相应的操作,比如对列表进行添加和删除值。
defaultdict 对象除了支持标准 dict 的操作,还支持以下方法作为扩展:
default_factory 属性是需要在实例化时提供的可写实例变量。如:
dd
# defaultdict(list, {'a': 1, 'b': 2, 'x': []})
dd.default_factory
# list
dd.default_factory = set
dd
# defaultdict(set, {'a': 1, 'b': 2, 'x': []})
dd.default_factory()
# set()
本属性由 missing__()
法来调用。如果构造对象时提供了第一个参数,则本属性会被初始化成那个参数,如果未提供第一个参数,则本属性为 None。
__missing__(key)
会调用 __getitem__
查找不存在的 key,伪代码为:
if self.default_factory is None:
raise KeyError((key,))
self[key] = value = self.default_factory()
return value
如果 default_factory 属性为 None,则调用本方法会抛出 KeyError 异常,附带参数 key。如果 default_factory 不为 None,则它会被(不带参数地)调用来为 key 提供一个默认值,这个值和 key 作为一对键值对被插入到字典中,并作为本方法的返回值返回。
如果调用 default_factory 时抛出了异常,这个异常会原封不动地向外层传递。在无法找到所需键值时,本方法会被 dict 中的 __getitem__()
方法调用。无论本方法返回了值还是抛出了异常,都会被 __getitem__()
传递。
注意,__missing__()
不会 被 __getitem__()
以外的其他方法调用。意味着 get() 会像正常的 dict 那样返回 None,而不是使用 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 用于计数(类似其他语言中的 bag 或 multiset):
s = 'mississippi'
d = defaultdict(int)
for k in s:
d[k] += 1
sorted(d.items())
# [('i', 4), ('m', 1), ('p', 2), ('s', 4)]
注:此例利用了 函数 int() 总是返回 0 的特殊情况,如果要返回特殊值可以使用 lambda。
使 defaultdict 用于构建 set 集合:
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in s:
d[k].add(v)
sorted(d.items())
# [('blue', {2, 4}), ('red', {1, 3})]
defaultdict 的主要特点是当您访问一个不存在的键时,它不会抛出 KeyError 异常,而是会根据您提供的默认工厂函数(default factory function)创建一个默认值。
以下是一些使用 defaultdict 的优点:
更新时间:Aug. 1, 2024, 12:06 p.m. 标签:python 字典 dict