juechafun/05-原子化笔记本/Python-排序.md

105 lines
3.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
#领域/Python
#复盘/5
## 一句话描述
[____Python排序____]
---
## 核心定义
围绕核心排序方法 `sorted()` 和 `list.sort()` 的实现,二者核心特性对比如下:
|特性|sorted(iterable)|list.sort()|
|---|---|---|
|返回值|返回**新的排序后列表**,原数据保持不变|无返回值None**原地修改**原列表|
|适用对象|所有可迭代对象(列表、元组、字典等)|仅列表list类型|
|内存占用|占用额外内存(生成新列表)|无额外内存消耗(原地修改)|
|常用场景|需保留原数据、非列表对象的排序需求|无需保留原数据、仅针对列表的排序场景|
## 基础排序用法
```python
# 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
```python
# 优先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`
```python
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)
```
## 性能优化技巧
### 提前排序键
对于大规模数据(万级以上),提前提取排序键(避免重复计算)
```python
# 先生成(键, 对象)元组列表,排序后提取对象(减少属性访问次数)
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 实现)
```python
# 等价于 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()`(原地修改)减少内存占用