用 operator 简化排序键:多字段排序与稳定性
用 operator 简化排序键
Python 的 sorted() 和 list.sort() 都通过 key 参数提取排序依据。简单场景常用 lambda,但从元组、字典或对象中提取固定字段时,标准库 operator 提供的工具通常更简洁,也更能直接表达意图。
使用 itemgetter 提取多个字段
operator.itemgetter() 适用于序列下标和映射键。传入多个位置时,它会返回由多个字段组成的元组,排序时依次比较各项。
from operator import itemgetter
rows = [
("u3", "Cara", 88),
("u1", "Bob", 95),
("u2", "Alice", 95),
("u4", "Bob", 88),
]
result = sorted(rows, key=itemgetter(2, 1))
for row in result:
print(row)
输出:
('u4', 'Bob', 88)
('u3', 'Cara', 88)
('u2', 'Alice', 95)
('u1', 'Bob', 95)
这里先按索引 2 的分数升序排列;分数相同时,再按索引 1 的姓名排列。对于字典,可以改为 itemgetter("score", "name")。如果元素缺少指定键或下标,会分别引发 KeyError 或 IndexError。
用稳定排序实现混合升降序
复合键配合 reverse=True 会反转整个比较结果,不能直接表示“部门升序、分数降序、姓名升序”。这类需求可以利用 Python 排序的稳定性:键相等的元素会保留原有相对顺序。按照从次要字段到主要字段的顺序执行多次排序即可。
from dataclasses import dataclass
from operator import attrgetter
@dataclass
class Student:
team: str
score: int
name: str
students = [
Student("B", 90, "Zoe"),
Student("A", 90, "Bob"),
Student("A", 95, "Cara"),
Student("A", 95, "Alice"),
Student("B", 90, "Adam"),
]
students.sort(key=attrgetter("name"))
students.sort(key=attrgetter("score"), reverse=True)
students.sort(key=attrgetter("team"))
for student in students:
print(student.team, student.score, student.name)
输出:
A 95 Alice
A 95 Cara
A 90 Bob
B 90 Adam
B 90 Zoe
最后一次排序按 team 分组,但同组元素仍保留此前形成的“分数降序、姓名升序”关系。attrgetter() 还支持一次提取多个属性,例如 attrgetter("team", "score");它也能通过 "profile.name" 这样的点分路径读取嵌套属性,但路径上的任意属性不存在时会引发 AttributeError。
按方法结果排序
methodcaller() 可以调用每个元素上的同名方法。例如按不区分大小写的文本结果排序:
from operator import methodcaller
names = ["alice", "ALICE", "Bob"]
print(sorted(names, key=methodcaller("casefold")))
输出:
['alice', 'ALICE', 'Bob']
前两个字符串的 casefold() 结果相同,因此保持输入顺序,这也是稳定性的直接体现。
边界条件与适用范围
排序键之间必须能够比较。混用整数与字符串、字段中同时出现 None 和数字,通常会引发 TypeError,应先统一数据类型或显式映射缺失值。浮点数 NaN 不具备普通数值的全序关系,也可能产生不直观的结果,重要数据应先清洗。
sorted() 返回新列表,适合保留原数据;list.sort() 原地修改列表并返回 None。operator 适合直接提取字段或调用固定方法;需要条件判断、类型转换或复杂缺失值策略时,普通函数往往比强行组合 getter 更清楚。
参考资料
- Python 文档 → 标准库 →
operator:标准运算符替代函数 - Python 文档 → 内置函数 →
sorted - Python 文档 → Python 使用指南 → 排序指南
本文由AI辅助编写,且示例需要读者自行验证。
- 点赞
- 收藏
- 关注作者
评论(0)