sort()原地排序不返回新列表,sorted()总返回新列表;两者均用timsort,性能差异主要在内存分配与数据复制。

sorted() 和 sort() 底层都用 Timsort,算法性能几乎一样;真正影响快慢的,是内存分配和是否需要复制数据。
sort() 不返回值,但会改原列表
调用 list.sort() 后,原列表直接重排,不产生新对象,返回 None。如果写成 new_list = my_list.sort(),new_list 就是 None,原列表虽已排序,但变量丢了引用。
- 常见错误:链式操作失败,比如
my_list.sort().reverse()报AttributeError - 适用场景:确定只用一次、后续不再需要原始顺序、且列表很大(如百万级元素)
- 注意:多线程/多协程中修改同一列表,需加锁,
sort()不是原子操作
sorted() 总是返回新 list,输入类型不限
sorted() 接收任意可迭代对象——tuple、set、str、生成器都行,但返回值固定是 list。这意味着哪怕你传入一个 tuple,也会被展开、排序、装进新 list 返回。
- 常见错误:对大元组或文件迭代器用
sorted(),会一次性读入内存,可能 OOM - 输入是生成器时,
sorted()必须先转成 list 才能排序,无法流式处理 - 想保持输入类型?得手动转换:
tuple(sorted(my_tuple))或set(sorted(my_set))(但 set 本身无序,转回去没意义)
key 函数调用开销在两者中完全一致
无论用 sort() 还是 sorted(),只要用了 key=...,每个元素都会调用一次该函数。性能瓶颈不在排序算法,而在 key 的计算成本。
- 避免在
key里做 I/O、网络请求、正则匹配等重操作 - 字符串忽略大小写排序,用
key=str.lower比key=lambda x: x.lower()略快(前者是内置方法) - 要按中文拼音排序,别每次调
lazy_pinyin(x),先预计算好键值列表再排序,或用functools.cache缓存结果 - 多字段排序优先用
operator.itemgetter(0, 2),比lambda x: (x[0], x[2])更快更安全
reverse=True 并不比两次排序快
reverse=True 只是翻转比较逻辑,不是先升序再反转。它和默认升序的复杂度一致,都是 O(n log n)。但要注意:它不能替代多条件升降混排。
- 要实现 “先按 age 升序,再按 score 降序”,不能写
key=lambda x: (x['age'], -x['score'])(仅适用于数字) - 更通用做法:先按次要字段降序
sorted(data, key=lambda x: x['score'], reverse=True),再按主要字段升序稳定排序 —— 因为 Timsort 是稳定排序 - 或者直接用元组:
sorted(data, key=lambda x: (x['age'], -x['score'])),前提是 score 全为数字且不为 None
最常被忽略的一点:如果你在循环里反复对同一份数据调用 sorted(),而其实只需要一次排序结果,那就纯属浪费 CPU 和内存;反过来,如果误用 sort() 导致上游数据被意外修改,调试时可能根本想不到是排序惹的祸。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











