【Python】.sort()与sorted()的区别与用法
Python中.sort()与sorted()的区别与用法详解
在Python编程中,排序是一项非常常见的操作。Python提供了两种主要的排序方法:.sort()
方法和sorted()
函数。虽然它们都能实现排序功能,但在使用方式和行为上有重要的区别。本文将详细解析这两种排序方法的区别、用法和适用场景。
1. .sort()方法
1.1 基本介绍
.sort()
是Python列表对象的一个方法,用于对列表进行原地排序。
特点:
- 直接修改原列表,不创建新列表
- 仅适用于列表对象
- 方法返回
None
- 更节省内存
1.2 语法
list.sort(key=None, reverse=False)
参数说明:
key
:指定一个函数,用于从每个列表元素中提取比较键reverse
:排序顺序,False
为升序(默认),True
为降序
1.3 使用示例
基本排序
# 数字列表排序
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(numbers) # 输出: [1, 1, 2, 3, 4, 5, 9]# 字符串列表排序
fruits = ['banana', 'apple', 'cherry', 'date']
fruits.sort()
print(fruits) # 输出: ['apple', 'banana', 'cherry', 'date']
降序排序
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort(reverse=True)
print(numbers) # 输出: [9, 5, 4, 3, 2, 1, 1]
使用key参数
# 按字符串长度排序
fruits = ['banana', 'apple', 'cherry', 'date']
fruits.sort(key=len)
print(fruits) # 输出: ['date', 'apple', 'banana', 'cherry']# 按绝对值排序
numbers = [-5, 3, -1, 4, -2]
numbers.sort(key=abs)
print(numbers) # 输出: [-1, -2, 3, 4, -5]
复杂数据排序
# 按字典的特定键排序
students = [{'name': 'Alice', 'age': 20, 'grade': 85},{'name': 'Bob', 'age': 19, 'grade': 92},{'name': 'Charlie', 'age': 20, 'grade': 78}
]# 按年龄排序
students.sort(key=lambda x: x['age'])
print(students)
# 输出: [{'name': 'Bob', 'age': 19, 'grade': 92},
# {'name': 'Alice', 'age': 20, 'grade': 85},
# {'name': 'Charlie', 'age': 20, 'grade': 78}]# 按多个条件排序(先按年龄,再按成绩)
students.sort(key=lambda x: (x['age'], x['grade']))
print(students)
2. sorted()函数
2.1 基本介绍
sorted()
是Python的内置函数,用于对任何可迭代对象进行排序。
特点:
- 返回一个新的排序列表,不修改原对象
- 适用于任何可迭代对象(列表、元组、字符串、字典等)
- 返回排序后的新列表
- 更灵活,适用于更多场景
2.2 语法
sorted(iterable, key=None, reverse=False)
参数说明:
iterable
:要排序的可迭代对象key
:指定一个函数,用于从每个元素中提取比较键reverse
:排序顺序,False
为升序(默认),True
为降序
2.3 使用示例
基本排序
# 列表排序
numbers = [3, 1, 4, 1, 5, 9, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # 输出: [1, 1, 2, 3, 4, 5, 9]
print(numbers) # 输出: [3, 1, 4, 1, 5, 9, 2] (原列表未改变)# 元组排序
tuple_data = (3, 1, 4, 1, 5)
sorted_tuple = sorted(tuple_data)
print(sorted_tuple) # 输出: [1, 1, 3, 4, 5] (注意:返回的是列表)
字符串排序
# 字符串排序
text = "python"
sorted_text = sorted(text)
print(sorted_text) # 输出: ['h', 'n', 'o', 'p', 't', 'y']# 将排序后的字符列表重新组合成字符串
sorted_string = ''.join(sorted(text))
print(sorted_string) # 输出: 'hnopty'
字典排序
# 字典按键排序
student_scores = {'Alice': 85, 'Bob': 92, 'Charlie': 78}
sorted_keys = sorted(student_scores)
print(sorted_keys) # 输出: ['Alice', 'Bob', 'Charlie']# 字典按值排序
sorted_by_value = sorted(student_scores.items(), key=lambda x: x[1])
print(sorted_by_value)
# 输出: [('Charlie', 78), ('Alice', 85), ('Bob', 92)]# 转换为有序字典
from collections import OrderedDict
ordered_scores = OrderedDict(sorted(student_scores.items(), key=lambda x: x[1]))
print(ordered_scores)
# 输出: OrderedDict([('Charlie', 78), ('Alice', 85), ('Bob', 92)])
复杂排序场景
# 按多个条件排序
students = [{'name': 'Alice', 'age': 20, 'grade': 85},{'name': 'Bob', 'age': 19, 'grade': 92},{'name': 'Charlie', 'age': 20, 'grade': 78}
]# 先按年龄升序,再按成绩降序
sorted_students = sorted(students, key=lambda x: (x['age'], -x['grade']))
print(sorted_students)# 使用operator模块
from operator import itemgetter, attrgetter# 使用itemgetter按多个键排序
sorted_students = sorted(students, key=itemgetter('age', 'grade'))
print(sorted_students)
3. 主要区别对比
特性 | .sort() | sorted() |
---|---|---|
返回值 | None | 新的排序列表 |
修改原对象 | 是(原地排序) | 否 |
适用对象 | 仅列表 | 任何可迭代对象 |
内存使用 | 更节省内存 | 需要额外内存创建新列表 |
函数类型 | 列表方法 | 内置函数 |
链式操作 | 不支持 | 支持 |
3.1 返回值差异
# .sort() 返回 None
numbers = [3, 1, 4]
result = numbers.sort()
print(result) # 输出: None
print(numbers) # 输出: [1, 3, 4]# sorted() 返回新列表
numbers = [3, 1, 4]
result = sorted(numbers)
print(result) # 输出: [1, 3, 4]
print(numbers) # 输出: [3, 1, 4] (原列表不变)
3.2 适用对象差异
# .sort() 仅适用于列表
numbers = [3, 1, 4]
numbers.sort() # 正确tuple_data = (3, 1, 4)
# tuple_data.sort() # 错误!元组没有sort方法# sorted() 适用于任何可迭代对象
numbers = [3, 1, 4]
sorted_list = sorted(numbers) # 正确tuple_data = (3, 1, 4)
sorted_tuple = sorted(tuple_data) # 正确,返回列表string_data = "python"
sorted_chars = sorted(string_data) # 正确,返回字符列表
4. 高级用法和技巧
4.1 自定义排序规则
# 自定义排序函数
def custom_sort(item):# 按字符串长度排序,长度相同按字母顺序return (len(item), item)words = ['apple', 'banana', 'cherry', 'date', 'fig']
sorted_words = sorted(words, key=custom_sort)
print(sorted_words) # 输出: ['fig', 'date', 'apple', 'banana', 'cherry']# 使用lambda表达式实现复杂排序
# 先按奇偶性,再按数值大小
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers, key=lambda x: (x % 2, x))
print(sorted_numbers) # 输出: [2, 4, 6, 1, 1, 3, 5, 9]
4.2 面向对象排序
class Student:def __init__(self, name, age, grade):self.name = nameself.age = ageself.grade = gradedef __repr__(self):return f"Student({self.name}, {self.age}, {self.grade})"students = [Student('Alice', 20, 85),Student('Bob', 19, 92),Student('Charlie', 20, 78)
]# 使用attrgetter排序
from operator import attrgetter# 按年龄排序
sorted_by_age = sorted(students, key=attrgetter('age'))
print(sorted_by_age)# 按多个属性排序
sorted_by_age_grade = sorted(students, key=attrgetter('age', 'grade'))
print(sorted_by_age_grade)
4.3 链式操作
# sorted()支持链式操作
text = "Hello World"# 排序 → 去重 → 连接字符串
result = ''.join(sorted(set(text.lower())))
print(result) # 输出: ' dehlorw'# 过滤 → 排序 → 转换
numbers = [5, -2, 8, -1, 3, -4]
result = sorted(filter(lambda x: x > 0, numbers))
print(result) # 输出: [3, 5, 8]
5. 性能考虑
5.1 时间和空间复杂度
两种方法的时间复杂度都是O(n log n),但空间复杂度不同:
.sort()
:O(1) 额外空间(原地排序)sorted()
:O(n) 额外空间(需要创建新列表)
5.2 性能测试
import time
import random# 生成大型测试数据
large_list = [random.randint(1, 100000) for _ in range(10000)]# 测试sorted()性能
start = time.time()
result1 = sorted(large_list)
time_sorted = time.time() - start# 测试.sort()性能
start = time.time()
large_list_copy = large_list.copy() # 创建副本以保持公平比较
large_list_copy.sort()
time_sort = time.time() - startprint(f"sorted() 耗时: {time_sorted:.6f}秒")
print(f".sort() 耗时: {time_sort:.6f}秒")
6. 使用场景建议
推荐使用.sort()
的情况:
- 需要原地排序,节省内存
- 不需要保留原始顺序
- 只处理列表对象
- 对大型数据集排序,内存受限
# 适合使用.sort()的场景
data = [5, 2, 8, 1, 9]
data.sort() # 直接修改原列表,节省内存
process_data(data) # 后续处理只需要排序后的数据
推荐使用sorted()
的情况:
- 需要保留原始数据不变
- 对非列表的可迭代对象排序
- 需要在表达式中使用排序结果
- 进行链式操作
- 函数式编程风格
# 适合使用sorted()的场景
original_data = [5, 2, 8, 1, 9]# 保留原数据,使用排序后的数据进行处理
processed_data = process_data(sorted(original_data))# 链式操作
result = process_chain(sorted(filter_condition, original_data))# 对非列表对象排序
tuple_data = (5, 2, 8, 1, 9)
sorted_data = sorted(tuple_data)
7. 常见错误和注意事项
7.1 错误使用.sort()的返回值
# 错误示例
numbers = [3, 1, 4]
sorted_numbers = numbers.sort() # sorted_numbers为None
print(sorted_numbers) # 输出: None# 正确用法
numbers = [3, 1, 4]
numbers.sort()
print(numbers) # 输出: [1, 3, 4]
7.2 对不可变对象使用.sort()
# 错误示例
tuple_data = (3, 1, 4)
# tuple_data.sort() # AttributeError: 'tuple' object has no attribute 'sort'# 正确用法
tuple_data = (3, 1, 4)
sorted_list = sorted(tuple_data) # 返回新列表
7.3 复杂对象的排序键选择
# 需要注意排序键的稳定性
data = [{'value': '10'}, {'value': '2'}, {'value': '1'}]# 字符串排序(可能不是期望的数字顺序)
sorted_str = sorted(data, key=lambda x: x['value'])
print(sorted_str) # 输出: [{'value': '1'}, {'value': '10'}, {'value': '2'}]# 数字排序
sorted_num = sorted(data, key=lambda x: int(x['value']))
print(sorted_num) # 输出: [{'value': '1'}, {'value': '2'}, {'value': '10'}]
总结
.sort()
和sorted()
都是Python中强大的排序工具,它们各有优缺点和适用场景:
.sort()
:高效、节省内存,适合对列表进行原地排序sorted()
:灵活、通用,适合需要保留原数据或处理各种可迭代对象的场景
选择哪个方法主要取决于具体需求:
- 如果需要修改原列表并且内存有限,使用
.sort()
- 如果需要保留原数据、进行链式操作或处理非列表对象,使用
sorted()
掌握这两种排序方法的区别和适用场景,能够帮助你在Python编程中更加高效地处理数据排序任务。
记住黄金法则:当你不确定该用哪个时,先考虑是否需要保留原始数据——如果需要,选择
sorted()
;如果不需要,选择.sort()
。