defaultdict 用于避免手动检查键是否存在,自动为未初始化的键提供默认值。它在分组数据、统计计数和构建嵌套字典结构时非常有用。1. 在分组场景中,可直接对键进行追加操作,无需判断键是否存在;2. 可替代计数器,通过 defaultdict(int) 自动初始化为0并累加;3. 支持构建多层嵌套字典结构,每层自动创建所需类型。使用时需注意,默认工厂函数必须是可调用对象,并非所有情况都适用,访问不存在的键会自动创建可能影响性能或逻辑安全。
在 python 中,defaultdict 是 collections 模块里一个非常实用的类,它继承自内置的 dict 类。与普通字典不同的是,当你访问一个不存在的键时,defaultdict 不会抛出 KeyError,而是自动创建一个默认值。这对于一些需要频繁初始化字典值的场景特别有用。
为什么用 defaultdict?
使用普通字典时,如果你尝试访问一个不存在的键并试图对其进行操作(比如追加元素),通常需要先判断这个键是否存在:
这种写法虽然可行,但代码显得有些冗余。而 defaultdict 可以简化这一过程:
from collections import defaultdict d = defaultdict(list) d['key'].append('value')
这里我们告诉 defaultdict,当访问不存在的键时,应该初始化一个空列表作为默认值,这样就可以直接进行 .append() 操作。
立即学习“Python免费学习笔记(深入)”;
defaultdict 的常见用途
1. 快速构建分组结构
这是 defaultdict 最常见的用途之一。例如,你有一组数据,想按照某个字段进行分类汇总:
data = [('a', 1), ('b', 2), ('a', 3), ('b', 4)] result = defaultdict(list) for key, value in data: result[key].append(value)
结果是:
{ 'a': [1, 3], 'b': [2, 4] }
- 这种方式避免了手动检查键是否存在的麻烦。
- 如果你用普通字典实现同样的功能,就需要每次都用 setdefault() 或者 if 判断。
2. 统计计数器(替代 Counter)
虽然 Counter 更适合做统计,但在某些情况下也可以用 defaultdict(int) 来实现类似功能:
words = ['apple', 'banana', 'apple', 'orange'] counts = defaultdict(int) for word in words: counts[word] += 1
结果是:
{ 'apple': 2, 'banana': 1, 'orange': 1 }
- defaultdict(int) 的意思是:遇到新键时,初始化为 0。
- 和 Counter 相比,这种方式更灵活,可以嵌套使用或其他类型结合。
3. 构建多层嵌套字典结构
有时候我们需要构造一个多级字典,比如按年、月、日组织数据。这时候可以用嵌套的 defaultdict:
from collections import defaultdict tree = defaultdict(Lambda: defaultdict(dict)) tree['2025']['April']['15'] = 'event'
上面这段代码不会报错,因为每一层都自动创建了下一层的结构。
- 使用 lambda 表达式可以让每层返回不同的默认类型。
- 如果你想让第二层也是 defaultdict,第三层才是普通字典或列表,都可以灵活组合。
注意事项和小技巧
- 默认工厂函数必须是可调用对象:比如 list、int、或者你自己定义的函数,不能是像 0 或 ‘str’ 这样的常量。
- 不是所有场景都适合 defaultdict:
- 如果你不希望字典在访问不存在键时“偷偷”创建新键,那还是用普通字典更安全。
- 在某些性能敏感的场景中,频繁调用默认工厂函数可能带来额外开销。
- defaultdict 不等于自动去重:很多人误以为它能自动处理重复键的问题,其实它只是方便初始化而已。
基本上就这些。掌握 defaultdict 能让你在处理字典逻辑时少些判断语句,代码更简洁清晰。