返回博客列表

Python字典分组的优雅之道:告别繁琐的if/else

探索Python中字典分组的高级技巧,掌握setdefault()和defaultdict的使用方法,让代码更简洁优雅。

2025-01-254 分钟阅读Yaron
#Python#字典#数据结构#最佳实践#Python3.8+

Python字典分组的优雅之道:告别繁琐的if/else

在数据处理中,一个极其常见的任务是按类别对项目进行分组,最典型的实现就是 {'类别A': [项目1, 项目2], '类别B': [项目3]} 这种值为列表的字典结构。

经典问题

当我们向这个字典添加新项目时,必须先判断类别(键)是否存在。如果不存在,需要先创建一个空列表,然后才能追加。
传统的做法是这样的:

data = {}  
words = ['apple', 'ant', 'ball', 'banana']

for word in words:
    key = word[0] # 按首字母分组
    if key not in data: 
        data[key] = [] # 如果键不存在,先创建空列表 
    data[key].append(word)

# data -> {'a': ['apple', 'ant'], 'b': ['ball', 'banana']}

这段代码虽然能用,但 if 判断显得有些累赘。Python 提供了两种更优雅的方式来处理。

方法一:通用利器 dict.setdefault()

setdefault() 是普通字典自带的一个方法,完美契合此场景。
核心思想: d.setdefault(key, default_value) 会查找 key。如果 key 不存在,它会设置 d[key] = default_value;无论如何,它最后总会返回 d[key] 的值
这意味着,我们总能得到一个列表,然后直接追加元素。
代码实现:

data = {}  
words = ['apple', 'ant', 'ball', 'banana']

for word in words:  
    key = word[0]  
    # 一行代码完成检查、创建和获取列表的操作  
    data.setdefault(key, []).append(word)

这行代码完全替代了之前的 if 块,简洁而高效。
适用场景: 对任何已存在的普通字典进行此类操作时的最佳选择。

方法二:专家之选 collections.defaultdict

如果你要从零开始构建一个用于分组的字典,defaultdict 是更专业的选择。
核心思想: 在创建 defaultdict 时,你指定一个“工厂函数”(如 list)。之后,每当你访问一个不存在的键时,它会自动调用工厂函数(list())来创建一个空列表作为该键的默认值。
代码实现:

from collections import defaultdict

# 创建时指定,任何新键的默认值都是一个空列表  
data = defaultdict(list)   
words = ['apple', 'ant', 'ball', 'banana']

for word in words:  
    key = word[0]  
    # 直接追加,无需任何检查。defaultdict 在背后处理了一切。  
    data[key].append(word)

代码的可读性达到了极致,循环体内只剩下最核心的 append 操作。
适用场景: 从头构建一个用于分组或计数的字典时的首选方案。

总结与建议

方法核心思想最佳使用场景
if/else手动检查键是否存在简单场景或教学演示
setdefault()获取键,若不存在则设置默认值任意普通字典进行操作
defaultdict访问不存在的键时自动创建默认值从零创建分组/计数专用字典

结论:

  • 要在普通字典上优雅地追加列表项,请使用 setdefault()
  • 新建一个分组字典,请选择 defaultdict,它能让你的代码最干净。

掌握这两种方法,能让你的 Python 代码在处理此类常见任务时,显得更加地道和专业。