在 Python 中,sort()和sorted()都用于排序,但核心区别在于:sort()是列表的方法,会直接修改原列表;而sorted()是内置函数,会返回一个新的排序后的列表,原列表不变。
具体区别如下表:
| 特性 | list.sort() | sorted(list) |
|---|---|---|
| 类型 | 列表的内置方法 | Python 内置函数 |
| 返回值 | None(直接修改原对象) | 返回一个新的排序列表 |
| 原对象 | 被修改 | 不被修改 |
| 适用对象 | 仅适用于列表 | 任何可迭代对象(如元组、字典、字符串等) |
| 使用方式 | list.sort() | sorted(iterable) |
一、示例
1. 对列表排序
nums = [3, 1, 4, 1, 5] # 使用 sort() nums.sort() print(nums) # 输出: [1, 1, 3, 4, 5] 原列表被改变 # 使用 sorted() nums = [3, 1, 4, 1, 5] new_nums = sorted(nums) print(nums) # 输出: [3, 1, 4, 1, 5] 原列表不变 print(new_nums) # 输出: [1, 1, 3, 4, 5] 新列表2. 对其他可迭代对象排序
# 元组 t = (3, 1, 2) print(sorted(t)) # 输出: [1, 2, 3] 返回列表 # t.sort() 会报错,因为元组没有 sort() 方法,以下等同 # 字符串 s = "python" print(sorted(s)) # 输出: ['h', 'n', 'o', 'p', 't', 'y'] # 字典(按键排序) d = {'b': 2, 'a': 1} print(sorted(d)) # 输出: ['a', 'b']3.两者都支持key和reverse参数:
# key:指定排序依据的函数 words = ["banana", "apple", "cherry"] words.sort(key=len) # 按字符串长度排序 print(words) # 输出: ['apple', 'banana', 'cherry'] # reverse:是否降序 nums = [3, 1, 4] print(sorted(nums, reverse=True)) # 输出: [4, 3, 1]为什么参数个数看起来不同?
list.sort()——只操作自身list.sort(key=None, reverse=False)
sort()是列表的方法,它隐式地知道自己要排序的对象就是调用它的列表本身。所以它只需要接收控制排序行为的参数(
key、reverse),不需要额外传入数据。
sorted()——需要指定排序对象sorted(iterable, key=None, reverse=False)
sorted()是独立的函数,它不知道你要排序什么,所以第一个参数必须传入可迭代对象。后面才是
key和reverse。
一、key和reverse对应什么?这两个参数在
sort()和sorted()中完全一样,用来定制排序规则。1.
key——指定排序依据
key接受一个函数,这个函数会被应用到每个元素上,然后根据函数的返回值进行排序。# 示例:按字符串长度排序 words = ["apple", "banana", "cherry", "date"] words.sort(key=len) print(words) # 输出: ['date', 'apple', 'banana', 'cherry'] # 示例:按元组的第二个元素排序 pairs = [(1, 'one'), (3, 'three'), (2, 'two')] pairs.sort(key=lambda x: x[1]) # 按字母顺序排序 print(pairs) # 输出: [(1, 'one'), (3, 'three'), (2, 'two')]2.
reverse——指定升序还是降序
reverse=False(默认):升序(从小到大)
reverse=True:降序(从大到小)nums = [3, 1, 4, 1, 5] # 升序(默认) nums.sort() print(nums) # [1, 1, 3, 4, 5] # 降序 nums.sort(reverse=True) print(nums) # [5, 4, 3, 1, 1]3. 组合使用
# 按字符串长度降序排序 words = ["apple", "banana", "cherry", "date"] sorted_words = sorted(words, key=len, reverse=True) print(sorted_words) # 输出: ['banana', 'cherry', 'apple', 'date']二、为什么需要
key而不是直接比较元素?因为有些对象不能直接比较,或者你想按某种规则排序:
# 无法直接比较不同类型 mixed = [1, 'a', 2, 'b'] # mixed.sort() # 会报错:TypeError # 使用 key 转换为可比较的类型 mixed.sort(key=str) # 全部转成字符串再比较 print(mixed) # [1, 2, 'a', 'b']
二、sort和sorted 对lambda的使用
lambda在排序中主要充当key参数,用于从每个元素中提取一个用于比较的“特征值”。
简单来说:lambda告诉 Python “按什么规则来排序”。
一、基础语法回顾
# sort 方法 list.sort(key=lambda x: 表达式, reverse=False) # sorted 函数 sorted(iterable, key=lambda x: 表达式, reverse=False)x:代表列表中的每一个元素表达式:返回用来排序的特征值
二、对简单数据结构的排序
1. 按元组的第二个元素排序
students = [('小明', 85), ('小红', 92), ('小刚', 78)] # 按分数升序 students.sort(key=lambda x: x[1]) print(students) # 输出: [('小刚', 78), ('小明', 85), ('小红', 92)] # 按分数降序 students.sort(key=lambda x: x[1], reverse=True) print(students) # 输出: [('小红', 92), ('小明', 85), ('小刚', 78)]2. 按字典的某个键排序
people = [ {'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35} ] # 按 age 排序 sorted_people = sorted(people, key=lambda x: x['age']) print(sorted_people) # 输出: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]三、对复杂数据结构的排序
1. 多级排序(先按成绩,再按年龄)
students = [ ('小明', 85, 18), ('小红', 92, 17), ('小刚', 85, 19), ('小丽', 92, 16) ] # 先按成绩降序,成绩相同再按年龄升序 students.sort(key=lambda x: (-x[1], x[2])) print(students) # 输出: [('小丽', 92, 16), ('小红', 92, 17), ('小刚', 85, 19), ('小明', 85, 18)]2. 按字符串的某个特征排序
# 按字符串长度排序 words = ['python', 'java', 'c', 'javascript', 'go'] words.sort(key=lambda x: len(x)) print(words) # 输出: ['c', 'go', 'java', 'python', 'javascript'] # 按最后一个字母排序 words.sort(key=lambda x: x[-1]) print(words) # 输出: ['java', 'python', 'c', 'javascript', 'go']为什么按元组的第二个元素排序是x[1],按最后一个字母排序是x[-1]
# 当列表元素是元组时 students = [('小明', 85), ('小红', 92)] # 排序时,x 依次等于 ('小明', 85) 和 ('小红', 92) # 要取元组内的元素,用索引:x[0] 是名字,x[1] 是分数 # 当列表元素是字符串时 words = ['apple', 'banana', 'cherry'] # 排序时,x 依次等于 'apple', 'banana', 'cherry' # 要取字符串内的字符,用索引:x[0] 是第一个字符,x[-1] 是最后一个字符拓展:
1.按字典的值
scores = {'小明': 85, '小红': 92, '小刚': 78} # 注意:sorted(dict) 是对字典的键排序 sorted_scores = sorted(scores.items(), key=lambda x: x[1]) # x 代表每个键值对元组:('小明', 85)、('小红', 92)、('小刚', 78) # x[1] 取分数:85、92、78 # 结果:[('小刚', 78), ('小明', 85), ('小红', 92)]2.按对象的属性
class Student: def __init__(self, name, score): self.name = name self.score = score students = [Student('小明', 85), Student('小红', 92)] # x 代表每个 Student 对象 # 取属性用 x.score,不是 x[1] students.sort(key=lambda x: x.score)
3. 结合split()处理字符串
# 按日志中的时间戳排序 logs = [ '2024-01-15 10:30:45 Error', '2024-01-15 08:20:10 Info', '2024-01-15 12:15:30 Warning' ] logs.sort(key=lambda x: x.split()[1]) # 按时间部分排序 print(logs) # 输出按 08:20:10, 10:30:45, 12:15:30 排序三、常见错误和注意事项
错误用法 1:lambda返回布尔值
# 错误:这样只会按 True/False 排序,不是你想要的效果 words = ['apple', 'banana', 'a', 'cherry'] words.sort(key=lambda x: len(x) > 3) # 错误示例 # 结果:['a', 'apple', 'banana', 'cherry'] 短的在前还是长的在前?不直观正确做法
# 正确:按实际长度排序 words.sort(key=lambda x: len(x))错误用法 2:忘记key=参数
# 错误:这样会把 lambda 本身当作排序对象 nums.sort(lambda x: abs(x)) # TypeError # 正确:必须指定 key= nums.sort(key=lambda x: abs(x))