
---
#领域/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()`（原地修改）减少内存占用