当前位置:首页 > 文章列表 > 文章 > python教程 > Python列表排序:sorted与sort详解

Python列表排序:sorted与sort详解

2025-09-30 10:35:52 0浏览 收藏

IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《Python列表排序:sorted与sort方法全解析》,聊聊,我们一起来看看吧!

Python中列表排序主要用list.sort()和sorted(),前者原地修改列表并返回None,后者返回新列表不改变原列表;选择取决于是否需保留原顺序,结合key参数可实现灵活排序,且Python排序稳定,适用于复杂数据类型。

python如何对列表进行排序_python列表排序sorted与sort方法详解

Python中对列表进行排序主要有两种核心方法:list.sort() 方法和内置的 sorted() 函数。简单来说,list.sort() 会直接修改原列表,原地完成排序,而 sorted() 函数则会返回一个新的已排序列表,保持原列表不变。选择哪一个取决于你是否需要保留原始列表的顺序。

解决方案

在Python中,对列表进行排序是日常编程中非常常见的操作,无论是处理用户输入、数据分析还是算法实现,排序都扮演着重要角色。理解 list.sort()sorted() 这两个工具的细微差别和各自的适用场景,是高效编写Python代码的关键。

1. list.sort() 方法

list.sort() 是列表对象的一个方法,它会直接在原地(in-place)修改列表,将其元素进行排序。这意味着调用后,原列表的内容就变成了排序后的结果,并且这个方法没有返回值(它返回 None)。

语法:list.sort(key=None, reverse=False)

  • key: (可选)一个函数,用于从每个列表元素中提取一个比较键。这个键将用于实际的比较操作。默认情况下,元素本身用于比较。
  • reverse: (可选)一个布尔值。如果设置为 True,列表将以降序(从大到小)排列;默认为 False,即升序排列。

示例:

numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"原始列表: {numbers}")

numbers.sort() # 默认升序排序
print(f"使用 sort() 升序排序后: {numbers}")

numbers_desc = [3, 1, 4, 1, 5, 9, 2, 6]
numbers_desc.sort(reverse=True) # 降序排序
print(f"使用 sort() 降序排序后: {numbers_desc}")

words = ["banana", "Apple", "cherry", "Date"]
words.sort(key=str.lower) # 忽略大小写排序
print(f"使用 sort() 忽略大小写排序后: {words}")

2. sorted() 函数

sorted() 是Python的内置函数,它可以接受任何可迭代对象(不仅仅是列表),并返回一个新的、已排序的列表。原始的可迭代对象不会被修改。

语法:sorted(iterable, key=None, reverse=False)

  • iterable: 任何可迭代对象(如列表、元组、字符串、字典的键等)。
  • key: (可选)与 list.sort() 中的 key 参数相同。
  • reverse: (可选)与 list.sort() 中的 reverse 参数相同。

示例:

data = (5, 2, 8, 1, 9) # 一个元组
print(f"原始元组: {data}")

sorted_list = sorted(data) # 返回一个新的列表
print(f"使用 sorted() 排序后的列表: {sorted_list}")
print(f"原始元组保持不变: {data}")

names = ["Charlie", "alice", "Bob"]
sorted_names = sorted(names, key=str.lower, reverse=True) # 忽略大小写降序
print(f"使用 sorted() 忽略大小写降序排序后的列表: {sorted_names}")
print(f"原始列表保持不变: {names}")

Python列表排序时,何时选择 sort() 而非 sorted()

选择 list.sort() 还是 sorted(),这其实是一个关于“副作用”和“内存管理”的权衡。我个人在编码时,如果确定不需要保留原始列表的状态,并且列表可能非常大,我会倾向于使用 list.sort()。这不完全是出于性能上的极致追求,更多时候是考虑到代码的意图和资源的合理利用。

list.sort() 的主要优势在于:

  1. 内存效率: 当处理非常大的列表时,list.sort() 由于是原地修改,不需要额外创建新的列表对象来存储排序结果。这意味着它在内存使用上更加高效。如果你的程序对内存占用敏感,或者列表的复制成本很高,sort() 是一个更好的选择。
  2. 性能略优: 通常情况下,原地排序会比创建一个新列表并填充它要快一些,因为它避免了新列表对象的创建和垃圾回收的开销。对于小列表,这种差异可以忽略不计,但对于百万级甚至千万级的列表,累积起来的性能提升就值得考虑了。
  3. 明确的意图: 当你明确知道你不再需要列表的原始顺序,并且希望它直接变成排序后的状态时,使用 sort() 可以更清晰地表达这种意图。这在一些数据预处理流程中很常见,比如你从数据库取出一批记录,然后直接对其进行排序以供后续处理,原顺序已经不重要了。

举个例子,假设你正在编写一个游戏,需要对一个包含数千个敌人的列表进行排序,以便找出最近的几个敌人。如果你每次都用 sorted() 创建一个新列表,那么在每一帧(或每次需要排序时),都会产生大量的临时列表对象,这可能会给垃圾回收器带来压力,甚至导致帧率下降。在这种情况下,直接对敌人列表进行 sort() 可能是更明智的选择。当然,这只是一个场景,实际情况要具体分析。

key 参数在Python列表排序中的高级用法是什么?

key 参数是Python排序功能中的一个“瑞士军刀”,它极大地扩展了排序的灵活性和表达力。它允许你定义一个函数,这个函数会在每个元素被比较之前被调用,并返回一个值。真正用于排序比较的,是这个函数的返回值,而不是元素本身。这使得我们可以根据元素的任何属性、计算结果甚至是复杂逻辑来排序。

以下是一些 key 参数的高级用法示例:

  1. 根据对象属性排序: 当你有一个自定义对象列表时,key 参数非常有用。

    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}, {self.stock} units)"
    
    products = [
        Product("Laptop", 1200, 50),
        Product("Mouse", 25, 200),
        Product("Keyboard", 75, 100),
        Product("Monitor", 300, 30)
    ]
    
    # 根据价格升序排序
    sorted_by_price = sorted(products, key=lambda p: p.price)
    print("按价格排序:", sorted_by_price)
    
    # 根据库存降序排序
    sorted_by_stock_desc = sorted(products, key=lambda p: p.stock, reverse=True)
    print("按库存降序排序:", sorted_by_stock_desc)
  2. 根据元组或列表的特定索引排序: 当列表包含元组或子列表时,你可以根据其中某个元素进行排序。

    students = [
        ("Alice", 20, "A"),
        ("Bob", 22, "C"),
        ("Charlie", 20, "B"),
        ("David", 21, "A")
    ]
    
    # 根据年龄排序
    sorted_by_age = sorted(students, key=lambda s: s[1])
    print("按年龄排序:", sorted_by_age)
    
    # 结合 operator.itemgetter 进行多级排序(更高效)
    from operator import itemgetter
    # 先按年龄,再按成绩(成绩A > B > C)
    # 注意:这里成绩是字符串,直接比较是按字母顺序,如果需要自定义成绩等级,key函数会更复杂
    sorted_by_age_then_grade = sorted(students, key=itemgetter(1, 2))
    print("按年龄再按成绩排序:", sorted_by_age_then_grade)
  3. 自定义复杂排序逻辑: key 函数可以包含任何你想要的复杂逻辑。

    file_names = ["img10.png", "img2.png", "img1.png", "img100.png"]
    
    # 按照文件名中的数字部分进行排序 (例如 img1.png, img2.png, img10.png, img100.png)
    import re
    def natural_sort_key(s):
        # 提取数字部分并转换为整数,非数字部分保持字符串
        return [int(text) if text.isdigit() else text.lower()
                for text in re.split('([0-9]+)', s)]
    
    sorted_files = sorted(file_names, key=natural_sort_key)
    print("自然排序文件:", sorted_files)

    这个 natural_sort_key 函数就是一个很好的例子,它使得原本按字典序排序会出错的字符串("img10" 在 "img2" 之前)能够按照我们人类的直觉进行排序。key 参数的强大之处在于,它将“如何比较”的细节封装起来,让排序接口保持简洁。

如何处理Python列表排序中的稳定性问题和复杂数据类型?

在Python中处理列表排序,除了知道如何用 sort()sorted(),理解“稳定性”以及如何应对“复杂数据类型”是进阶的关键。这些点,在我看来,是区分一个熟练的Python开发者和初学者的重要标志。

1. 排序稳定性(Stability)

Python的内置排序算法(Timsort,它是归并排序和插入排序的混合体)是稳定的。这意味着如果两个元素在排序时具有相同的键(或者说,它们在比较时被认为是相等的),那么它们在排序后的列表中会保持它们在原始列表中的相对顺序。

为什么稳定性很重要? 考虑一个场景:你有一份学生名单,每个学生有姓名和分数。

  • 你首先按姓名首字母排序。
  • 然后,你希望按分数降序排序,但对于分数相同的学生,你希望他们保持原先按姓名排序的顺序。

如果排序算法不稳定,第二次按分数排序可能会打乱第一次按姓名排序的相对顺序。但因为Python的排序是稳定的,你可以先按次要标准排序,再按主要标准排序,就能达到多级排序的效果。

示例:

data = [('apple', 3), ('banana', 1), ('cherry', 3), ('date', 2)]

# 先按字母顺序排序(次要标准)
sorted_by_name = sorted(data, key=lambda x: x[0])
print("按名称排序:", sorted_by_name)
# 输出: [('apple', 3), ('banana', 1), ('cherry', 3), ('date', 2)]

# 再按数字降序排序(主要标准),注意稳定性
# 对于数字相同的元素,它们在 sorted_by_name 中的相对顺序会被保留
final_sorted = sorted(sorted_by_name, key=lambda x: x[1], reverse=True)
print("先按名称再按数字降序排序:", final_sorted)
# 输出: [('apple', 3), ('cherry', 3), ('date', 2), ('banana', 1)]
# 注意 'apple' 和 'cherry' 都是3,它们在最终结果中仍然保持了 'apple' 在 'cherry' 之前的顺序,这就是稳定性。

在实际项目中,多级排序的需求很常见,理解稳定性可以让你更自信地构建复杂的排序逻辑。

2. 复杂数据类型的排序

当列表中的元素不是简单的数字或字符串,而是自定义对象、混合类型元组等复杂数据类型时,直接排序可能会遇到问题,或者需要更精细的控制。

  • 自定义对象: 如果你有一个自定义类的实例列表,直接调用 sorted()list.sort() 而不提供 key 参数,Python可能会抛出 TypeError,因为默认情况下它不知道如何比较你的对象。

    解决方案1:使用 key 参数(最常用、最灵活) 正如前面所述,通过 key 参数提供一个函数,告诉Python如何从每个对象中提取一个可比较的值。这是处理自定义对象排序的首选方法,因为它不修改类的定义,可以在不同场景下提供不同的排序逻辑。

    解决方案2:实现 __lt__ 方法(定义对象的自然顺序) 如果你希望你的自定义对象能够“自然地”排序,即它们有一个默认的、固定的比较逻辑,你可以在类中实现 __lt__ (less than) 魔术方法。当Python需要比较两个对象时,如果它们没有提供 key 参数,就会尝试调用这个方法。

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __repr__(self):
            return f"Person('{self.name}', {self.age})"
    
        # 定义小于操作符,使得 Person 对象可以根据年龄进行比较
        def __lt__(self, other):
            if not isinstance(other, Person):
                return NotImplemented
            return self.age < other.age
    
    people = [Person('Alice', 30), Person('Bob', 25), Person('Charlie', 30)]
    
    # 现在可以直接排序,因为 Person 类定义了 __lt__
    sorted_people = sorted(people)
    print("按年龄自然排序:", sorted_people)
    
    # 仍然可以使用 key 参数覆盖默认行为,例如按姓名排序
    sorted_by_name = sorted(people, key=lambda p: p.name)
    print("按姓名排序:", sorted_by_name)

    实现 __lt__ 方法,可以让你的对象在很多Python内置函数和数据结构中(例如 min(), max(), heapq 模块)也能够自然地工作,这是一种更深层次的集成。

  • 混合类型列表: Python 3 默认不允许对不同类型的元素进行比较(例如,1 < 'a' 会抛出 TypeError)。如果你的列表中包含混合类型,并且需要排序,你必须提供一个 key 函数来将所有元素转换为可比较的类型,或者处理这些类型差异。

    mixed_list = [5, "apple", 2, "banana", 10]
    
    # 这会报错:TypeError: '<' not supported between instances of 'str' and 'int'
    # sorted_mixed = sorted(mixed_list)
    
    # 解决方案:使用 key 函数,将所有元素转换为字符串进行比较
    sorted_mixed_str = sorted(mixed_list, key=str)
    print("混合类型按字符串排序:", sorted_mixed_str) # 输出: [10, 2, 5, 'apple', 'banana']
    
    # 或者,更复杂的逻辑,例如先按类型分组,再在组内排序
    def custom_mixed_sort_key(item):
        if isinstance(item, int):
            return (0, item) # 数字排在前面
        elif isinstance(item, str):
            return (1, item) # 字符串排在后面
        return (2, str(item)) # 其他类型
    
    sorted_mixed_custom = sorted(mixed_list, key=custom_mixed_sort_key)
    print("混合类型自定义排序:", sorted_mixed_custom) # 输出: [2, 5, 10, 'apple', 'banana']

    处理复杂数据类型时,关键在于清晰地定义你希望的比较逻辑。key 参数和 __lt__ 方法为你提供了强大的工具来表达这些逻辑,让排序行为符合你的预期。

好了,本文到此结束,带大家了解了《Python列表排序:sorted与sort详解》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!

京东医院app实用吗?功能服务全面测评京东医院app实用吗?功能服务全面测评
上一篇
京东医院app实用吗?功能服务全面测评
JavaScript处理大数据前端展示技巧
下一篇
JavaScript处理大数据前端展示技巧
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    499次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • WisPaper:复旦大学智能科研助手,AI文献搜索、阅读与总结
    WisPaper
    WisPaper是复旦大学团队研发的智能科研助手,提供AI文献精准搜索、智能翻译与核心总结功能,助您高效搜读海量学术文献,全面提升科研效率。
    92次使用
  • Canva可画AI简历生成器:智能制作专业简历,高效求职利器
    Canva可画-AI简历生成器
    探索Canva可画AI简历生成器,融合AI智能分析、润色与多语言翻译,提供海量专业模板及个性化设计。助您高效创建独特简历,轻松应对各类求职挑战,提升成功率。
    110次使用
  • AI 试衣:潮际好麦,电商营销素材一键生成
    潮际好麦-AI试衣
    潮际好麦 AI 试衣平台,助力电商营销、设计领域,提供静态试衣图、动态试衣视频等全方位服务,高效打造高质量商品展示素材。
    195次使用
  • 蝉妈妈AI:国内首个电商垂直大模型,抖音增长智能助手
    蝉妈妈AI
    蝉妈妈AI是国内首个聚焦电商领域的垂直大模型应用,深度融合独家电商数据库与DeepSeek-R1大模型。作为电商人专属智能助手,它重构电商运营全链路,助力抖音等内容电商商家实现数据分析、策略生成、内容创作与效果优化,平均提升GMV 230%,是您降本增效、抢占增长先机的关键。
    394次使用
  • 社媒分析AI:数说Social Research,用AI读懂社媒,驱动增长
    数说Social Research-社媒分析AI Agent
    数说Social Research是数说故事旗下社媒智能研究平台,依托AI Social Power,提供全域社媒数据采集、垂直大模型分析及行业场景化应用,助力品牌实现“数据-洞察-决策”全链路支持。
    256次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码