juechafun/05-原子化笔记本/Python-排序.md
2026-01-15 10:01:16 +08:00

3.2 KiB
Raw Blame History

#领域/Python

一句话描述

[Python 核心排序方法sorted () 与 list.sort ())的特性对比、基础用法、自定义排序规则及性能优化技巧____]

核心定义

围绕核心排序方法 sorted() 和 list.sort() 的实现,二者核心特性对比如下:

特性 sorted(iterable) list.sort()
返回值 返回新的排序后列表,原数据保持不变 无返回值None原地修改原列表
适用对象 所有可迭代对象(列表、元组、字典等) 仅列表list类型
内存占用 占用额外内存(生成新列表) 无额外内存消耗(原地修改)
常用场景 需保留原数据、非列表对象的排序需求 无需保留原数据、仅针对列表的排序场景

基础排序用法

# sorted():生成新列表 
nums = [3, 1, 2] 
new_nums = sorted(nums) # new_nums=[1,2,3], nums仍为[3,1,2] 

# list.sort():原地修改 
nums.sort() # nums变为[1,2,3]返回None

自定义排序规则

1. key 参数lambda / 自定义函数)

  • 单维度排序:key=lambda 元素: 元素.属性
  • 多维度排序:key=lambda 元素: (属性1, 属性2)(优先按属性 1相等则按属性 2
# 优先x升序 → 其次y升序你的核心需求 
sorted_list = sorted(msg_list, key=lambda m: (m.x, m.y))

# 反向优先x降序 → 其次y降序 
sorted_list_rev = sorted(msg_list, key=lambda m: (m.x, m.y), reverse=True)

# 更复杂场景x升序y降序混合方向 
sorted_list_mix = sorted(msg_list, key=lambda m: (m.x, -m.y)) # -y实现y降序

重写类的比较方法(lt

如果某个类的排序规则是 “长期固定” 的,可重写类的__lt__小于方法Python 排序会自动基于<推导其他比较逻辑,无需指定key

class Msg:
	# x, y 属性
	
	# 定义“小于”规则先比x再比y 
	def __lt__(self, other): 
		if not isinstance(other, Msg): # 避免类型错误,提升健壮性 
			return NotImplemented 
		if self.x != other.x: 
				return self.x < other.x 
		return self.y < other.y

# 直接排序无需key 
sorted_list = sorted(msg_list)

性能优化技巧

提前排序键

对于大规模数据(万级以上),提前提取排序键(避免重复计算)

# 先生成(键, 对象)元组列表,排序后提取对象(减少属性访问次数) 
key_obj = [( (m.x, m.y), m ) for m in msg_list] 
key_obj.sort() 
sorted_list = [obj for (key, obj) in key_obj]

避免在key中使用复杂计算(如函数调用),优先预计算。

operator 替代 lambda

内置的 operator.attrgetter 更简洁、大规模数据下性能更好(底层是 C 实现)

# 等价于 lambda m: (m.x, m.y),但更快、更简洁
sorted_list = sorted(msg_list, key=attrgetter("x", "y"))
print(sorted_list)  # [Msg(i=2, x=1, y=3), Msg(i=3, x=2, y=1), Msg(i=1, x=3, y=2)]

# 反向排序x降→y升
sorted_rev = sorted(msg_list, key=attrgetter("x", "y"), reverse=True)

注意事项

  • 避免在 key 中使用复杂函数调用,优先通过预计算简化排序键
  • 大规模数据排序时,优先选择 list.sort()(原地修改)减少内存占用