在日常写代码时,经常会遇到需要给列表排序的场景。比如整理学生成绩、按价格排列商品、或者把一堆文件名按字母顺序排好。Python 提供了内置的排序方法 sort() 和 sorted(),用起来简单,但背后其实有一套讲究的机制。
两种排序方式的区别
list.sort() 是直接修改原列表,不返回新对象。适合在不需要保留原始顺序时使用。
numbers = [3, 1, 4, 1, 5]
numbers.sort()
print(numbers) # 输出:[1, 1, 3, 4, 5]
而 sorted() 不动原列表,返回一个新的排好序的列表。当你还想留着原来的顺序时,这个更合适。
words = ['banana', 'apple', 'cherry']
ordered = sorted(words)
print(ordered) # 输出:['apple', 'banana', 'cherry']
print(words) # 原列表不变:['banana', 'apple', 'cherry']
排序背后的算法:Timsort
Python 的排序不是简单的冒泡或快排,而是用了一种叫 Timsort 的算法。这是由 Tim Peters 在 2002 年为 Python 设计的,结合了归并排序和插入排序的优点。
它特别擅长处理现实中常见的数据:比如部分有序的序列、有重复值的列表、或者包含多个递增或递减小段的数据。像你从数据库读出的一批订单记录,可能本身就按时间大致有序,Timsort 能快速识别这些片段,减少比较次数。
稳定排序带来的便利
Timsort 是稳定排序,意味着相等元素的相对位置不会改变。这个特性在多条件排序时很有用。
比如一个学生成绩表,先按班级排,再按分数排。如果排序不稳定,同分的学生可能乱掉顺序。而 Python 的排序能保证:分数相同的情况下,原来靠前的人依然靠前。
students = [
('一班', 85),
('二班', 90),
('一班', 85),
('二班', 87)
]
# 先按班级,再按成绩
sorted_students = sorted(students, key=lambda x: (x[0], x[1]))
# 两个一班85分的学生,原始顺序会被保留
自定义排序规则
有时候默认的字典序不够用。比如想按字符串长度排,或者对复杂对象提取某个字段排序。这时可以用 key 参数。
names = ['Alice', 'Bob', 'Charlie']
sorted_by_len = sorted(names, key=len)
print(sorted_by_len) # 输出:['Bob', 'Alice', 'Charlie']
key 接收一个函数,系统会自动拿每个元素去调这个函数,然后根据返回值来比大小。常见用法还有 str.lower 实现忽略大小写的排序。
逆序排列
加个 reverse=True 就能倒过来排。不管是数字从大到小,还是字母从 Z 到 A,都是一行搞定。
prices = [199, 98, 256, 300]
descending = sorted(prices, reverse=True)
print(descending) # 输出:[300, 256, 199, 98]
这个参数不影响稳定性,只是把最终结果翻个个儿,内部比较逻辑还是一样可靠。