Python 排序与内存占用的关系

1次阅读

sorted() 新建列表致内存翻倍,list.sort() 原地排序几乎零增量;不可变类型只能用 sorted();key 函数需避免耗时操作,宜预处理或用 itemgetter;大数据应选 heapq 或外部排序。

Python 排序与内存占用的关系

sorted() 和 list.sort() 的内存差异很真实

python 排序操作不是“免费的”,sorted() 会新建列表,list.sort() 是原地排序——这直接决定你程序吃不吃得消。尤其处理几十万行日志、上百万条记录时,差的不是几毫秒,是几百MB内存。

  • sorted() 返回新列表,原列表不变,内存占用 ≈ 原数据 × 2(临时副本 + 结果)
  • list.sort() 不返回值(返回 None),只改原列表,内存增量几乎为 0
  • 如果后续不再需要原始顺序,硬用 sorted() 就是主动给自己加压
  • 注意:字符串、元组等不可变类型只能用 sorted(),因为没 .sort() 方法

key 参数写错会导致隐式复制和性能暴跌

很多人以为 key=Lambda x: x[1] 只是“取第二项”,但若 x 是大对象(比如含 json 字段的字典),每次调用 lambda 都可能触发深层拷贝或计算——特别是 key 函数里写了 json.loads()re.search() 或访问数据库字段时。

  • 避免在 key 里做耗时操作;先预处理好排序键,存成新字段或缓存列表
  • operator.itemgetter('field') 替代 lambda x: x['field'],更快且不引发意外引用
  • 如果 key 计算结果可复用(比如解析一次时间戳),提前算好并 zip 到数据中:list(zip(parsed_keys, data)),再按第一列排序

小数据用内置排序,大数据考虑 heapq 或外部排序

Python 的 Timsort 在小到中等规模(

  • 确认数据量:用 sys.getsizeof() 粗略估算总内存(注意它不计嵌套对象,需递归估算)
  • 单次排序 >500MB?别硬扛,改用 heapq.merge() 分块排序合并,或导出到 sqliteORDER BY
  • heapq.nsmallest(n, iterable) 比先 sorted()切片快得多,尤其当 n

自定义类排序时 __lt__ 实现不当会悄悄吃内存

给类加 __lt__ 支持排序很常见,但若里面调用了 self.to_dict()json.dumps(self),每次比较都生成新对象,排序 O(n log n) 次调用 = O(n log n) 次内存分配。

立即学习Python免费学习笔记(深入)”;

  • 只在 __lt__ 里比核心字段,比如 return self.priority
  • 避免在比较方法里做序列化、格式化、网络请求等副作用操作
  • 如果必须依赖复杂逻辑,提前把排序键存在实例属性里(如 self._sort_key = compute_key(self)),然后直接比这个属性

排序本身不慢,慢的是你没意识到每个函数调用、每次对象创建、每一份隐式副本都在堆上留下痕迹。真正卡住的往往不是算法复杂度,而是某次 sorted([huge_dict_list], key=lambda d: d['config']['timeout']) —— 那个 ['config']['timeout'] 路径查找,底层反复构造中间 dict 视图,没人告诉你它不便宜。

text=ZqhQzanResources