当前位置:首页>python>Python collections 全解析:Counter、defaultdict、namedtuple 一篇搞定

Python collections 全解析:Counter、defaultdict、namedtuple 一篇搞定

  • 2026-09-02 18:55:01
Python collections 全解析:Counter、defaultdict、namedtuple 一篇搞定

字数 1026,阅读大约需 6 分钟

Python collections 全解析

你有没有遇到过这种情况:统计一个列表里每个元素出现了多少次,写了七八行代码,结果同事一行 Counter 就搞定了?

Python 标准库里的 collections 模块,是那种"不知道的时候觉得没必要,知道了之后天天用"的存在。今天把最常用的三个——Counter、defaultdict、namedtuple——一次性讲透。

Counter:统计这件事,别再手写了

Counter 是专门用来计数的字典子类。最常见的场景:统计词频、统计元素出现次数。

1
2
3
4
5
6

from collections import Counterwords = ["python", "java", "python", "go", "python", "java"]count = Counter(words)print(count)# Counter({'python': 3, 'java': 2, 'go': 1})

不只是列表,字符串也能直接统计:

1
2
3

c = Counter("abracadabra")print(c.most_common(3))# [('a', 5), ('b', 2), ('r', 2)]

most_common(n) 直接返回出现最多的前 n 个,省去排序的麻烦。

Counter 还支持加减运算,两个 Counter 可以直接相加合并,或者相减取差值:

1
2
3
4

c1 = Counter(a=3, b=2)c2 = Counter(a=1, b=4, c=1)print(c1 + c2)  # Counter({'b': 6, 'a': 4, 'c': 1})print(c1 - c2)  # Counter({'a': 2})  # 负数自动过滤

什么时候用 Counter?只要你想"统计"两个字,先想 Counter,再想别的。

defaultdict:KeyError 再也不用 try-except 了

普通字典访问不存在的 key 会抛 KeyError,处理起来要么 get(),要么 setdefault(),要么 try-except,总之麻烦。

defaultdict 的思路是:给字典一个"默认工厂",访问不存在的 key 时自动创建默认值。

1
2
3
4
5
6
7
8

from collections import defaultdictitems = [("水果", "苹果"), ("蔬菜", "白菜"), ("水果", "香蕉"), ("蔬菜", "菠菜")]grouped = defaultdict(list)for category, item in items:    grouped[category].append(item)print(dict(grouped))# {'水果': ['苹果', '香蕉'], '蔬菜': ['白菜', '菠菜']}

如果用普通字典,你得先判断 key 存不存在,再决定是 append 还是初始化列表。用 defaultdict(list) 直接省掉这一步。

常用的默认工厂:

1
2
3
4

d_int = defaultdict(int)     # 默认值 0,适合计数d_list = defaultdict(list)   # 默认值 [],适合分组d_set = defaultdict(set)     # 默认值 set(),适合去重分组d_str = defaultdict(str)     # 默认值 ""

还可以传自定义函数:

1
2
3
4

d = defaultdict(lambda: "未知")d["name"] = "肥鱼"print(d["name"])    # 肥鱼print(d["age"])     # 未知(自动创建)

注意一个坑:defaultdict 访问不存在的 key 会自动创建,所以 key in d 之后再访问,和直接访问效果不同——直接访问会把 key 写进去。如果你只是想"查一下有没有",用 d.get(key) 更安全。

namedtuple:比字典轻,比类简单

有时候你需要一个简单的数据结构,用字典吧感觉太松散,用类吧又觉得小题大做。namedtuple 就是这个中间地带。

1
2
3
4
5
6
7

from collections import namedtuplePoint = namedtuple("Point", ["x", "y"])p = Point(3, 4)print(p.x, p.y)   # 3 4print(p[0], p[1]) # 3 4(也支持索引访问)print(p)          # Point(x=3, y=4)

它本质上是元组,所以是不可变的,也可以解包:

1
2

x, y = pprint(x, y)  # 3 4

实际项目里,namedtuple 特别适合表示"有固定字段的数据记录",比如数据库查询结果、配置项、坐标点:

1
2
3

Employee = namedtuple("Employee", ["name", "department", "salary"])emp = Employee("张三", "技术部", 15000)print(f"{emp.name} 在 {emp.department},月薪 {emp.salary}")

比字典的好处:字段名固定,不会写错 key;比类的好处:不用写 init,代码更简洁。

namedtuple 还有个 _replace() 方法,可以基于现有实例创建修改了某些字段的新实例(因为元组不可变,所以是"新建"而不是"修改"):

1
2

emp2 = emp._replace(salary=18000)print(emp2)  # Employee(name='张三', department='技术部', salary=18000)

三者对比,什么时候用哪个

场景
推荐
统计元素出现次数
Counter
字典值需要默认初始化(列表、集合、数字)
defaultdict
需要有字段名的轻量数据结构
namedtuple
需要可变的有字段名结构
dataclass(Python 3.7+)

collections 模块里还有 deque(双端队列)、OrderedDict(有序字典,Python 3.7+ 普通字典已有序)等,但上面三个是日常开发里用得最频繁的。

把这三个用熟了,你会发现很多"需要写一堆代码"的场景,其实标准库早就帮你想好了。

你还知道哪些好的编程学习方法?欢迎在评论区分享!

开发必备神器

  1. 强大的编程神器:IntelliJ IDEA 免费激活

  2. 轻松安装 MySQL 数据库

  3. 数据库管理神器 - Navicat 的奇妙之旅

  4. 宝藏级的开发手册,前后端开发语言都有,自己也在用

·················END·················

最新文章

随机文章