一、前言
在 Python 编程中,列表(List) 是最常用的数据结构之一。而对列表进行排序是日常开发中最常见的需求之一,无论是处理数字、字符串还是复杂对象,掌握排序技巧都能显著提升编程效率。
本文将系统性地介绍 Python 中列表排序的方法与技巧,包括内置函数、关键字参数、自定义排序逻辑等,并结合大量代码示例和实际应用场景,帮助你全面掌握列表排序的核心知识。
二、Python 列表排序的基本方式
1. 使用 .sort() 方法 —— 原地排序
.sort() 是列表的一个原地排序方法,会直接修改原始列表:
nums = [5, 2, 9, 1, 7]
nums.sort()
print(nums) # [1, 2, 5, 7, 9]
✅ 特点:
- 改变原始列表;
- 无返回值;
- 效率高,适合大数据量排序。
2. 使用 sorted() 函数 —— 返回新列表
sorted() 是一个内置函数,不会修改原始列表,而是返回一个新的排序后的列表:
nums = [5, 2, 9, 1, 7]
sorted_nums = sorted(nums)
print(sorted_nums) # [1, 2, 5, 7, 9]
print(nums) # [5, 2, 9, 1, 7](原列表未改变)
✅ 特点:
- 不修改原始列表;
- 返回新列表;
- 更适合需要保留原始数据的场景。
三、控制排序顺序(升序 / 降序)
默认情况下,Python 按照升序进行排序。可以通过 reverse 参数来控制排序方向:
升序排序(默认)
nums = [5, 2, 9, 1, 7]
nums.sort()
print(nums) # [1, 2, 5, 7, 9]
降序排序
nums.sort(reverse=True)
print(nums) # [9, 7, 5, 2, 1]
同样适用于 sorted():
sorted_nums = sorted(nums, reverse=True)
四、对字符串列表排序
Python 默认按照字母顺序(ASCII 值)进行排序:
words = ['banana', 'apple', 'cherry', 'Apricot']
words.sort()
print(words) # ['Apricot', 'apple', 'banana', 'cherry']
⚠️ 注意:大写字母在 ASCII 表中排在小写字母前面,因此
'Apricot'排在'apple'前面。
如果你希望忽略大小写进行排序,可以使用 key=str.lower:
words.sort(key=str.lower)
print(words) # ['apple', 'Apricot', 'banana', 'cherry']
五、自定义排序规则 —— 使用 key 参数
key 参数允许我们传入一个函数,用于生成排序依据的“键”。
示例 1:按字符串长度排序
words = ['apple', 'fig', 'banana', 'pear']
words.sort(key=len)
print(words) # ['fig', 'pear', 'apple', 'banana']
示例 2:按元组中的某个字段排序
students = [('Alice', 25), ('Bob', 20), ('Charlie', 30)]
students.sort(key=lambda x: x[1]) # 按年龄排序
print(students) # [('Bob', 20), ('Alice', 25), ('Charlie', 30)]
示例 3:组合多个排序条件(稳定排序)
Python 的排序是稳定的,即当两个元素相等时,它们的相对位置不变。我们可以利用这一点实现多条件排序:
data = [ (2, 'a'), (1, 'b'), (2, 'c'), (1, 'a')]
# 先按第一个字段排序,再按第二个字段排序
data.sort(key=lambda x: (x[0], x[1]))
print(data) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'c')]
六、对自定义对象排序
如果列表中存储的是自定义类的对象,你可以通过 key 参数指定排序依据。
示例:对 Person 对象按年龄排序
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"{self.name}({self.age})"
people = [
Person("Alice", 30),
Person("Bob", 25),
Person("Charlie", 30)
]
people.sort(key=lambda p: (p.age, p.name)) # 先按年龄,再按名字排序
print(people)
# 输出:[Bob(25), Alice(30), Charlie(30)]
七、常见问题与注意事项
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 混合类型排序报错 | int 和 str 不能比较 | 确保列表元素类型一致 |
| 忽略大小写排序失败 | 默认区分大小写 | 使用 key=str.lower |
| 自定义对象排序出错 | 未提供 key 函数 | 提供 key 或实现 __lt__ 方法 |
| 多条件排序顺序混乱 | 未正确嵌套排序条件 | 使用元组 (field1, field2) 作为 key |
八、总结对比表
| 操作 | 方法 | 是否修改原列表 | 特点 |
|---|---|---|---|
| 原地排序 | .sort() | ✅ 是 | 速度快,不占额外内存 |
| 非原地排序 | sorted() | ❌ 否 | 保留原数据,更安全 |
| 控制排序方向 | reverse=True/False | ✅ 支持 | 可用于 .sort() 和 sorted() |
| 自定义排序 | key=func | ✅ 支持 | 支持 lambda、函数、属性等 |
| 忽略大小写排序 | key=str.lower | ✅ 支持 | 字符串列表推荐用法 |
| 多条件排序 | key=lambda x: (x.f1, x.f2) | ✅ 支持 | 利用稳定排序特性 |
| 对象排序 | key=lambda obj: obj.attr | ✅ 支持 | 需明确指定排序字段 |
九、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!