整体说明
defaultdict是 Python 标准库collections模块中的一个工具,继承自普通字典dictdefaultdict的核心特点是:访问不存在的键时,会自动创建该键并赋予默认值- 无需手动判断
key in dict或使用dict.get(key, 默认值)
- 无需手动判断
defaultdict的核心是 “自动处理不存在的键” ,适合以下场景:- 统计计数(
defaultdict(int)) - 分组聚合(
defaultdict(list)/set) - 避免频繁判断
key in dict或dict.get()
- 统计计数(
defaultdict 基本用法
- 初始化:指定“默认值工厂函数”:
defaultdict的构造函数接收一个 可调用对象(工厂函数) ,当访问不存在的键时,会调用该函数生成默认值 - 常见的工厂函数可以是:
- 内置类型:
int(默认 0)、list(默认空列表)、set(默认空集合)、str(默认空字符串) - 自定义函数:返回固定值或动态生成的值
- 内置类型:
- 可以用于解决普通字典的痛点:访问不存在的键会抛出
KeyError1
2
3
4
5
6
7
8# 普通字典:访问不存在的键报错
d = {}
print(d["foo"]) # KeyError: 'foo'
# defaultdict:自动创建键并赋予默认值
from collections import defaultdict
dd = defaultdict(int) # 默认值为 0
print(dd["foo"]) # 输出 0,且 dd 现在是 {'foo': 0}
defaultdict 使用示例
统计元素出现次数(用
int作工厂)1
2
3
4
5
6
7
8
9from collections import defaultdict
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
count = defaultdict(int) # 键不存在时默认值为 0
for word in words:
count[word] += 1 # 无需判断键是否存在,直接累加
print(dict(count)) # 转为普通字典:{'apple': 3, 'banana': 2, 'orange': 1}分组(用
list作工厂):将元素按某个规则分组,值为列表(自动创建空列表,避免手动append时报错):1
2
3
4
5
6
7
8
9
10from collections import defaultdict
students = [("Alice", "Math"), ("Bob", "English"), ("Alice", "Physics"), ("Bob", "Math")]
group = defaultdict(list) # 键不存在时默认值为 []
for name, subject in students:
group[name].append(subject) # 直接向列表添加元素
print(dict(group))
# 输出:{'Alice': ['Math', 'Physics'], 'Bob': ['English', 'Math']}去重分组(用
set作工厂):值为集合 set,自动去重:1
2
3
4
5
6
7
8
9from collections import defaultdict
data = [("a", 1), ("b", 2), ("a", 1), ("b", 3)]
group = defaultdict(set) # 键不存在时默认值为 set()
for key, val in data:
group[key].add(val) # 集合自动去重
print(dict(group)) # 输出:{'a': {1}, 'b': {2, 3}}自定义默认值(用自定义函数作工厂):如果需要非内置的默认值(如
None、固定字符串、动态值),可传入自定义函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15from collections import defaultdict
# 自定义工厂函数:返回固定值 "unknown"
def default_val():
return "unknown"
dd = defaultdict(default_val)
print(dd["foo"]) # 输出 "unknown",dd 变为 {'foo': 'unknown'}
# 简化:用 lambda 表达式(适合简单默认值)
dd2 = defaultdict(lambda: None) # 默认值为 None
print(dd2["bar"]) # 输出 None
dd3 = defaultdict(lambda: [1, 2, 3]) # 默认值为 [1,2,3]
print(dd3["baz"]) # 输出 [1,2,3]
特别注意 dict.fromkeys()
dict.fromkeys()也能设置默认值,但会为所有键共享同一个可变对象(如列表),容易踩坑:1
2
3
4
5
6
7
8
9# 普通 dict.fromkeys() 的坑:所有键共享同一个列表
d = dict.fromkeys(["a", "b"], [])
d["a"].append(1)
print(d) # {'a': [1], 'b': [1]}(意外修改了 b 的值)
# defaultdict 无此问题:每个键的列表是独立的
dd = defaultdict(list)
dd["a"].append(1)
print(dd) # {'a': [1]}(b 未被创建)