Python列表排序方法详解
编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《Python列表排序全攻略》,文章讲解的知识点主要包括,如果你对文章方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。
Python中排序列表最常用的方法是list.sort()和sorted()函数。list.sort()直接修改原列表,不返回新列表,适用于无需保留原始顺序的场景;sorted()则返回一个新的已排序列表,原列表保持不变,适合需要保留原始数据的情况。两者均支持reverse参数进行降序排序,并使用高效的Timsort算法。关键区别在于:list.sort()是原地操作,节省内存;sorted()无副作用,更安全灵活。对于复杂排序需求,可通过key参数传入函数实现自定义规则,如按对象属性、忽略大小写或多重条件排序。处理混合数据类型时,可设计key函数统一比较逻辑,确保不同类型元素能正确排序。掌握这两种方法及其适用场景,有助于编写高效且可维护的代码。

Python中对列表进行排序,最直接且常用的方法就是利用其内置的list.sort()方法或者sorted()函数。它们都能帮你把杂乱无章的列表变得井然有序,只是在使用场景和效果上有些微妙的区别,理解这些差异是高效编程的关键。
解决方案
当我们需要对Python列表进行排序时,通常会用到两个核心工具:list.sort()方法和sorted()内置函数。
list.sort()是一个列表对象的方法,它会直接修改原列表,进行“原地”排序,并且不返回任何值(准确地说是返回None)。这就像你整理书架,直接把书在书架上重新排列,而不会搬到另一个地方整理。
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"原始列表: {my_list}")
my_list.sort() # 对原列表进行排序
print(f"排序后的列表 (list.sort()): {my_list}") # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
# 降序排序也很简单
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
my_list.sort(reverse=True)
print(f"降序排序后的列表: {my_list}") # 输出: [9, 6, 5, 4, 3, 2, 1, 1]而sorted()是一个内置函数,它接受一个可迭代对象(不限于列表)作为参数,然后返回一个新的、已排序的列表,而原始的可迭代对象则保持不变。这就像你把书架上的书拍了张照,然后根据照片重新写了一份目录,书架上的书本身没动。
another_list = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"原始列表: {another_list}")
new_sorted_list = sorted(another_list) # 返回一个新的已排序列表
print(f"sorted()返回的新列表: {new_sorted_list}") # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
print(f"原始列表 (未改变): {another_list}") # 输出: [3, 1, 4, 1, 5, 9, 2, 6]
# sorted()同样支持降序
new_desc_list = sorted(another_list, reverse=True)
print(f"sorted()降序返回的新列表: {new_desc_list}") # 输出: [9, 6, 5, 4, 3, 2, 1, 1]这两个方法都默认进行升序排序。如果需要降序,只需将reverse参数设置为True即可。它们内部都使用了Timsort算法,这是一种混合排序算法,在实际应用中表现非常优秀,因为它结合了归并排序和插入排序的优点。
Python中in-place排序与创建新列表排序的区别是什么?
在我看来,理解list.sort()和sorted()之间最核心的差异,就是它们对内存和原始数据的影响。这不只是语法上的不同,更是编程思维和资源管理上的考量。
list.sort()是典型的“原地(in-place)”操作。它直接在内存中修改了列表对象本身,没有创建新的列表。这意味着,如果你有一个非常大的列表,并且你确定不再需要其原始的未排序状态,那么使用list.sort()会更高效,因为它避免了创建新列表所需的额外内存开销。它的返回值为None,这其实是一个非常明确的信号:这个方法的主要作用是“副作用”(修改了对象),而不是“返回值”。我个人觉得,当你看到一个方法返回None时,潜意识里就应该知道它可能对调用者有直接影响。
反观sorted()函数,它则是一个“纯函数”的代表。它不触碰原始的可迭代对象,而是基于它创建一个全新的、已排序的列表并返回。这种方式的优点在于“无副作用”,原始数据始终保持完整。这在很多场景下非常有用,比如你需要保留原始列表以供后续其他操作,或者你正在编写一个函数,不希望意外地修改传入的参数。当然,这种做法的代价是需要额外的内存来存储新的列表。对于小型列表,这通常不是问题;但对于内存敏感的大型数据集,就得权衡一下了。
举个例子,假设你正在处理用户输入的一串数字,你既想展示排序后的结果,又想保留原始输入以便进行其他分析(比如计算平均值,而排序会打乱原始顺序)。这时,sorted()就是你的不二之选。但如果你的任务只是简单地对一个列表进行排序,然后就用排序后的结果,原始列表的顺序就不再重要,那么list.sort()无疑是更经济的选择。我有时候会纠结,到底用哪个,但通常会倾向于sorted(),除非我明确知道原地修改更优,因为“无副作用”的代码更容易理解和维护,也更不容易引入意外的bug。
如何使用自定义规则对Python列表进行排序?
Python的排序功能远不止升序降序那么简单,它允许你通过key参数传入一个函数,来定义非常灵活的排序规则。这就像给排序算法提供了一个“翻译官”,告诉它“嘿,别直接比较元素本身,先用这个函数处理一下,然后根据处理后的结果来比较!”
这个key参数接受一个单参数函数,这个函数会对列表中的每个元素进行一次处理,然后排序算法会根据这些处理后的结果来决定元素的顺序。这对于排序包含复杂对象的列表特别有用。
最常见的用法是配合lambda表达式,实现简洁的自定义排序。
# 1. 排序字符串列表,忽略大小写
words = ["apple", "Banana", "cherry", "Date"]
# 默认排序会把大写字母排在前面
print(f"默认排序: {sorted(words)}") # 输出: ['Banana', 'Date', 'apple', 'cherry']
# 使用key=str.lower忽略大小写
print(f"忽略大小写排序: {sorted(words, key=str.lower)}") # 输出: ['apple', 'Banana', 'cherry', 'Date']
# 2. 排序元组列表,根据元组的第二个元素
students = [("Alice", 20, "Math"), ("Bob", 18, "Physics"), ("Charlie", 22, "Chemistry")]
# 默认排序是根据第一个元素
print(f"默认排序: {sorted(students)}")
# 根据年龄(第二个元素)排序
print(f"按年龄排序: {sorted(students, key=lambda student: student[1])}") # 输出: [('Bob', 18, 'Physics'), ('Alice', 20, 'Math'), ('Charlie', 22, 'Chemistry')]
# 3. 排序自定义对象列表
class Product:
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def __repr__(self): # 为了打印时好看
return f"Product({self.name}, ${self.price}, Stock:{self.stock})"
products = [
Product("Laptop", 1200, 50),
Product("Mouse", 25, 200),
Product("Keyboard", 75, 100),
Product("Monitor", 300, 30)
]
# 按价格排序
print(f"按价格排序: {sorted(products, key=lambda p: p.price)}")
# 按库存量排序 (降序)
print(f"按库存降序排序: {sorted(products, key=lambda p: p.stock, reverse=True)}")
# 4. 甚至可以按多个条件排序
# 先按价格升序,价格相同再按库存降序
# 注意:key函数返回一个元组,Python会按元组的顺序进行比较
print(f"按价格升序,库存降序: {sorted(products, key=lambda p: (p.price, -p.stock))}")
# 这里的-p.stock是为了实现降序,因为默认是升序比较使用key参数时,你提供的函数会作用于列表中的每一个元素,生成一个用于比较的“代理值”。这个代理值可以是任何可比较的类型,比如数字、字符串、甚至元组。当key函数返回一个元组时,Python会按照元组元素的顺序进行逐个比较,直到找到不同的元素或者元组结束,这在处理多条件排序时非常强大。我个人觉得,掌握key参数的使用,是真正玩转Python排序的标志。
Python列表排序时,如何处理混合数据类型或复杂对象?
处理混合数据类型或者复杂对象的排序,确实是排序操作中比较有挑战性的一个方面。Python的默认排序机制,在面对不同类型的数据时,通常会因为无法确定比较规则而抛出TypeError。比如,你不能直接比较一个整数和一个字符串。
# 混合数据类型示例 mixed_list = [1, "hello", 3.14, "world", 2] # sorted(mixed_list) # 这会抛出 TypeError: '<' not supported between instances of 'str' and 'int'
要解决这个问题,核心思路依然是利用key参数,为每种类型的数据提供一个统一的“可比较”的代理值。
1. 处理混合数据类型:
当列表包含多种类型的数据时,你可以编写一个key函数,根据元素的类型来返回一个适合比较的值。这通常涉及到为不同类型的数据定义一个“优先级”或者一个统一的表示。
mixed_list = [1, "hello", 3.14, "world", 2, "Python"]
def custom_key_for_mixed_types(item):
if isinstance(item, int):
return (0, item) # 整数优先级最高,然后按值排序
elif isinstance(item, float):
return (1, item) # 浮点数次之
elif isinstance(item, str):
return (2, item.lower()) # 字符串优先级最低,按小写字母排序
else:
return (3, str(item)) # 其他类型,转换为字符串处理
print(f"混合类型排序: {sorted(mixed_list, key=custom_key_for_mixed_types)}")
# 输出: [1, 2, 3.14, 'hello', 'Python', 'world']这里,我给每种类型分配了一个优先级(元组的第一个元素),然后用元素本身(或其转换形式)作为元组的第二个元素。这样,Python在比较时,会先比较优先级,优先级相同再比较实际值。这是一种非常实用的策略。
2. 处理复杂对象(自定义类的实例): 对于自定义类的实例,如果没有特别指定,Python默认会比较它们的内存地址,这通常不是我们想要的。要让自定义对象可排序,有几种方法:
使用
key参数(最常用且推荐): 就像前面提到的Product例子,通过key=lambda obj: obj.attribute来指定根据哪个属性进行排序。这是最灵活和非侵入性的方法。实现特殊方法
__lt__等: 如果你希望你的自定义对象在任何情况下都能直接进行比较(比如obj1 < obj2),那么可以在类中实现富比较方法,特别是__lt__(less than)。Python的functools.total_ordering装饰器可以帮助你减少代码量,只需要实现__lt__和一个相等方法(__eq__),它就能自动为你生成其他比较方法。from functools import total_ordering @total_ordering class Book: def __init__(self, title, author, pages): self.title = title self.author = author self.pages = pages def __repr__(self): return f"Book('{self.title}', '{self.author}', {self.pages}页)" def __eq__(self, other): if not isinstance(other, Book): return NotImplemented return (self.title, self.author, self.pages) == \ (other.title, other.author, other.pages) def __lt__(self, other): # 定义小于操作,这里按页数排序 if not isinstance(other, Book): return NotImplemented return self.pages < other.pages books = [ Book("Python Crash Course", "Eric Matthes", 544), Book("Fluent Python", "Luciano Ramalho", 912), Book("Automate the Boring Stuff", "Al Sweigart", 500) ] print(f"按页数排序 (__lt__): {sorted(books)}") # 输出: [Book('Automate the Boring Stuff', 'Al Sweigart', 500页), Book('Python Crash Course', 'Eric Matthes', 544页), Book('Fluent Python', 'Luciano Ramalho', 912页)]这种方式的好处是,一旦定义了比较规则,你的对象就可以在任何需要比较的地方直接使用,而不仅仅是排序。但缺点是,它将排序逻辑“硬编码”到了类定义中,如果需要多种排序方式,可能就得回到
key参数了。我通常会根据对象的“自然顺序”来决定是否实现__lt__,如果对象有一个非常明确的主导排序属性,那就实现它;否则,key参数是更灵活的选择。
在处理这些复杂场景时,关键在于把不同类型或复杂对象“映射”到一个可比较的统一形式。这个映射过程就是key函数的工作。这确保了排序算法总能拿到它能理解和处理的数据,避免了类型不匹配带来的混乱。
终于介绍完啦!小伙伴们,这篇关于《Python列表排序方法详解》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!
JavaScript无障碍优化技巧分享
- 上一篇
- JavaScript无障碍优化技巧分享
- 下一篇
- 美图秀秀裁剪问题解决技巧
-
- 文章 · python教程 | 23分钟前 |
- Python多线程GIL详解与影响分析
- 322浏览 收藏
-
- 文章 · python教程 | 52分钟前 | 游戏开发 Pygame 碰撞检测 Python飞机大战 精灵组
- Python飞机大战小游戏开发教程
- 147浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python画皮卡丘教程及代码分享
- 397浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python3数组旋转算法详解
- 173浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- PythonSeries方法详解与实战技巧
- 113浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Pydantic字段不可变性实现方法
- 485浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python字符串替换实用技巧分享
- 326浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python日期格式解析与验证技巧
- 220浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- PythonOpenCV像素操作教程
- 362浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python条件优化:告别嵌套if-else陷阱
- 147浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Pandas与NumPyNaN查找区别详解
- 278浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3172次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3383次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3412次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4517次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3792次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

