Python中defatultdict的概念、作用、常见用法举例 详解
在 Python 中,collections.defaultdict 是一个非常有用的数据结构,它是 dict 的子类,
区别在于它可以为不存在的键提供一个默认值,而不需要显式检查键是否存在。
以下是 defaultdict 的常见用法举例,涵盖不同场景:
1. 基本用法:为不存在的键提供默认值
defaultdict 需要一个工厂函数(如 int, list, set 等)来生成默认值。
from collections import defaultdict # 使用 int 作为默认工厂,键不存在时返回 0 d = defaultdict(int) d['a'] += 1 # 不需要初始化,键 'a' 自动赋值为 0 + 1 print(d) # 输出: defaultdict(<class 'int'>, {'a': 1}) # 使用 list 作为默认工厂,键不存在时返回空列表 d = defaultdict(list) d['a'].append(1) # 不需要初始化,直接追加 d['b'].append(2) print(d) # 输出: defaultdict(<class 'list'>, {'a': [1], 'b': [2]}) # 使用 set 作为默认工厂,键不存在时返回空集合 d = defaultdict(set) d['a'].add(1) # 直接添加 d['a'].add(2) print(d) # 输出: defaultdict(<class 'set'>, {'a': {1, 2}})
2. 计数器(统计出现次数)
常用于统计元素出现次数,替代手动检查和初始化。
from collections import defaultdict # 统计字符串中每个字符的出现次数 text = "hello world" char_count = defaultdict(int) for char in text: char_count[char] += 1 print(char_count) # 输出: defaultdict(<class 'int'>, {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
3. 分组(按键分组数据)
用于将数据按某个键分组,类似 SQL 的 GROUP BY。
from collections import defaultdict # 按年龄分组人员 people = [ {"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}, {"name": "Charlie", "age": 25} ] age_groups = defaultdict(list) for person in people: age_groups[person["age"]].append(person["name"]) print(age_groups) # 输出: defaultdict(<class 'list'>, {25: ['Alice', 'Charlie'], 30: ['Bob']})
4. 嵌套 defaultdict
用于处理多级嵌套字典,避免多次检查键是否存在。
from collections import defaultdict # 创建嵌套 defaultdict nested_dict = defaultdict(lambda: defaultdict(int)) nested_dict['a']['b'] += 1 # 直接操作嵌套键 nested_dict['a']['c'] += 2 print(nested_dict) # 输出: defaultdict(<function <lambda> at ...>, {'a': defaultdict(<class 'int'>, {'b': 1, 'c': 2})})
5. 累加值(累加数字或列表)
用于累加值或构建复杂数据结构。
from collections import defaultdict # 累加每个键的值 scores = [('Alice', 100), ('Bob', 200), ('Alice', 150)] score_sum = defaultdict(int) for name, score in scores: score_sum[name] += score print(score_sum) # 输出: defaultdict(<class 'int'>, {'Alice': 250, 'Bob': 200}) # 收集每个键的多个值 data = [('cat', 'meow'), ('dog', 'woof'), ('cat', 'purr')] sounds = defaultdict(list) for animal, sound in data: sounds[animal].append(sound) print(sounds) # 输出: defaultdict(<class 'list'>, {'cat': ['meow', 'purr'], 'dog': ['woof']})
6. 自定义默认值
可以自定义默认值生成函数,灵活处理复杂场景。
from collections import defaultdict # 自定义默认值为特定的字符串 d = defaultdict(lambda: "Unknown") d['a'] = "Apple" print(d['a']) # 输出: Apple print(d['b']) # 输出: Unknown
7. 与普通字典的对比
使用普通字典时,需要手动检查键是否存在,否则会抛出 KeyError:
# 普通字典 d = {} # 需要检查键是否存在 if 'a' not in d: d['a'] = 0 d['a'] += 1 # 使用 defaultdict 更简洁 d = defaultdict(int) d['a'] += 1 # 直接操作
8. 复杂默认值生成
普通函数可以包含复杂的逻辑,例如根据全局状态或外部条件生成默认值。
from collections import defaultdict from datetime import datetime # 记录访问时间和初始计数 def default_log_entry(): return {"count": 0, "last_access": datetime.now()} log = defaultdict(default_log_entry) log['user1']['count'] += 1 log['user2']['count'] += 2 print(log) # 输出: defaultdict(<function default_log_entry at ...>, { # 'user1': {'count': 1, 'last_access': 2023-...}, # 'user2': {'count': 2, 'last_access': 2023-...} # })
注意事项
- 性能:defaultdict 的性能与普通字典几乎相同,但在处理大量键不存在的场景时更简洁高效。
- 默认值不可变:如果使用 list 或 set 作为默认工厂,每次访问不存在的键都会返回一个新对象,不会影响其他键。
- 序列化:defaultdict 不能直接用 json.dumps 序列化,需先转换为普通字典(如 dict(d))。

浙公网安备 33010602011771号