分享|Python 中 sort() 和 sorted() 的适用场景与高级用法
匿名用户
343
2025.07.11
2025.07.11
发布于 广东

【python基础包functools的cmp_to_key, 比较方法和关键方法-亢保星-哔哩哔哩】

基本区别

  • sorted(): 内置函数,返回新的排序列表,不改变原序列
  • list.sort(): 列表方法,原地排序,返回 None,改变原列表

适用场景

使用 sorted() 的情况:

  1. 需要保留原序列不变
  2. 对不可变序列(如元组、字符串)排序
  3. 对任何可迭代对象排序(包括字典、集合等)
  4. 需要将排序结果直接用于表达式或作为参数传递

使用 list.sort() 的情况:

  1. 对列表进行原地排序以节省内存
  2. 不需要保留原列表顺序
  3. 处理大数据集时(避免创建副本的内存开销)

高级用法

1. 自定义排序键

# 按字符串长度排序
words = ['apple', 'banana', 'cherry', 'date']
sorted_words = sorted(words, key=len)  # ['date', 'apple', 'banana', 'cherry']

# 按字典的某个值排序
students = [{'name': 'Alice', 'grade': 90}, {'name': 'Bob', 'grade': 85}]
sorted_students = sorted(students, key=lambda x: x['grade'], reverse=True)

2. 多级排序

# 先按年龄升序,再按分数降序
data = [('Alice', 25, 88), ('Bob', 25, 92), ('Charlie', 23, 95)]
sorted_data = sorted(data, key=lambda x: (x[1], -x[2]))

3. 使用 operator 模块

from operator import itemgetter, attrgetter

# 按元组第二个元素排序
sorted([(1, 2), (3, 1), (5, 0)], key=itemgetter(1))

# 按对象属性排序
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
people = [Person('Alice', 25), Person('Bob', 20)]
sorted_people = sorted(people, key=attrgetter('age'))

4. 稳定排序

Python 的排序是稳定的,意味着相等元素的相对顺序保持不变:

data = [('red', 1), ('blue', 1), ('red', 2)]
# 按第二个元素排序后,两个红色元素的相对顺序保持不变
sorted_data = sorted(data, key=lambda x: x[1])

5. 自定义比较函数(Python 3 中使用 functools.cmp_to_key)

from functools import cmp_to_key

def compare(a, b):
    if a % 2 == b % 2:
        return a - b
    return -1 if a % 2 else 1

numbers = [1, 2, 3, 4, 5, 6]
sorted_numbers = sorted(numbers, key=cmp_to_key(compare))
# 结果: [1, 3, 5, 2, 4, 6] (奇数在前,偶数在后,各自升序)

6. 处理 None 值

# 将 None 值放在最后
data = [1, None, 3, 2, None]
sorted_data = sorted(data, key=lambda x: (x is None, x))

元组比较规则

Python 在比较元组时,会 从左到右逐元素比较

  1. 先比较 x is NoneFalse < True
  2. 如果 x is None 相同(即都是 False 或都是 True),再比较 x 本身。

排序逻辑

  • None 的元素(False, x)
    → 先按 False 排序(比 True 小),然后按 x 排序。
  • None 的元素(True, None)
    → 由于 TrueFalse 大,所以 None 会排在最后。

7. 性能优化

对于复杂对象的排序,预先计算键可以提升性能:

# 普通方式
sorted_data = sorted(data, key=lambda x: x.some_expensive_operation())

# 优化方式 - 预先计算
decorated = [(x.some_expensive_operation(), x) for x in data]
decorated.sort()
sorted_data = [x for (key, x) in decorated]

总结

选择 sort() 还是 sorted() 主要取决于是否需要保留原序列以及内存考虑。高级排序技巧可以处理复杂的数据结构排序需求,通过合理使用 key 参数和比较函数,可以实现几乎任何自定义排序逻辑。

评论 (0)