python 内建排序 HOW TO

本文深入讲解Python中的list.sort()与sorted()函数的区别及应用。包括原地排序与返回新列表的不同,以及对任意迭代器排序的能力。重点介绍key参数的作用,如使用lambda表达式和operator模块简化排序过程。此外,还探讨了reverse参数与cmp参数的使用方法。

list.sort()与sorted()


python 有两个内建排序函数:一个是list.sort(),对调用该函数的list进行原地排序;另一个是sorted(),可以对任意迭代器进行排序,返回list类型的序列。二者有两个区别。


第一,list.sort()没有返回值,只对list原地排序;而sorted()将排序后序列作为新list返回,如下实例:

>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]


第二,list.sort()只应用于list,而sorted()可用于任意迭代器,如下实例:

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]


另外,二者都有相同参数:1.key  2.reverse  3.cmp,并且使用方法相同,下面通过sorted()进行详细说明




key参数的使用


基本说明:

key参数指定一个函数,这个函数的实参为每个迭代器的item,经过该函数运算,返回值为每个item中需要进行对比的项(key),如下实例:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

简单说,key参数值必须是一个函数,且这个函数只有一个参数,并且返回一个key值,作为比较使用。



使用实例说明:

通常情况下,对于复杂结构进行排序,通常使用索引作为比较的key,例如:

>>> student_tuples = [
    ('john', 'A', 15),
    ('jane', 'B', 12),
    ('dave', 'B', 10),
]
>>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

类似的排序方式,也可以用于类,例如:

>>> class Student:
        def __init__(self, name, grade, age):
            self.name = name
            self.grade = grade
            self.age = age
        def __repr__(self):
            return repr((self.name, self.grade, self.age))

>>>

>>> student_objects = [
    Student('john', 'A', 15),
    Student('jane', 'B', 12),
    Student('dave', 'B', 10),
]
>>> sorted(student_objects, key=lambda student: student.age)   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]



使用Operator模块

由于以上使用key参数的方式十分普遍,python提供了相关函数,使以上方式的使用更加简单快捷。


operator模块提供了 operator.itemgetter(),operator.attrgetter()函数,在 Python 2.5以后还提供了operator.methodcaller() 函数。使用这些函数可以让上节描述的排序方法更加快捷方便:

>>> from operator import itemgetter, attrgetter

>>>

>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>>

>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]


operater模块提供的函数,可以进行多级排序. 如下实例, 先以grade排序,再以 age排序:

>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

>>>

>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]


operator.methodcaller()函数可以调用方法,操作需要比较的item后,然后对item进行比较。如下实例,str.count()方法对每个item的感叹号进行统计,按照包含感叹号的多少进行排序:

>>> messages = ['critical!!!', 'hurry!', 'standby', 'immediate!!']
>>> sorted(messages, key=methodcaller('count', '!'))
['standby', 'hurry!', 'immediate!!', 'critical!!!']

reverse参数的使用

reverse参数很好理解,如果reverse=True,将以降序排序,如下实例:

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

>>>

>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]


cmp参数的使用(不推荐)

在python2.4以前,排序没有key参数,所有进行自定义排序,使用的都是cmp参数。而在python 3开始,就没有cmp参数了,另外cmp参数没有key运行得快,所以这里只做简单说明,建议大家尽量使用key参数进行排序


cmp参数值是一个有两个参数的函数,该函数参数的实参也是需要比较的item,通过该函数进行计算,返回的结果如果为负数,证明item1<item2,若为0,证明item1=item2,为正数,证明item1>item2。如下例子:

>>> def numeric_compare(x, y):
        return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]

刚才说道python3.x不支持cmp参数,如何将python2.x程序迁移到python3.x呢?使用下述方法:

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K


>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]

在python2.7以后,functools.cmp_to_key() 可直接通过functools进行调用



另外一些说明

一、为类组成的列表,提供默认的排序方法

在类中将排序中作为key的属性,加入相关比较的方法中,如下:

>>> Student.__eq__ = lambda self, other: self.age == other.age
>>> Student.__ne__ = lambda self, other: self.age != other.age
>>> Student.__lt__ = lambda self, other: self.age < other.age
>>> Student.__le__ = lambda self, other: self.age <= other.age
>>> Student.__gt__ = lambda self, other: self.age > other.age
>>> Student.__ge__ = lambda self, other: self.age >= other.age
>>> sorted(student_objects)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]


一般以实现这六种比较方法为佳,另外可以使用functools.total_ordering()修饰,可以简化代码量


二、key参数的另一种用法

key参数不只依赖被排序的实例,可以使用额外的实例作为key。如下例子:student 成绩存在一个字典中, 此字典可以用于给另一个包含student姓名的list排序::

>>> students = ['dave', 'john', 'jane']
>>> grades = {'john': 'F', 'jane':'A', 'dave': 'C'}
>>> sorted(students, key=grades.__getitem__)
['jane', 'dave', 'john']

参考:

http://docs.python.org/2/howto/sorting.html

<think>好的,我现在需要帮助用户获取Python编程的学习指南,特别是针对初学者。首先,我得回顾用户提供的引用内容,看看哪些资源适合推荐。用户提到的Wikibooks作为入门资源,还有Python的官方文档,这些都是不错的学习材料。另外,用户还提到社区支持和聊天机器人的使用,这些可能对初学者有帮助。 接下来,我需要按照系统级指令来组织回答。必须使用中文,结构清晰,分步骤说明。同时,要生成相关问题,并正确应用引用标识。需要注意数学表达式和代码块的格式,不过在这个问题中可能用到的数学内容不多,但如果有的话,比如算法复杂度,需要用$...$或$$...$$格式。用户的需求是学习Python的指南,所以应该从基础开始,逐步深入。根据引用内容,Wikibooks适合入门,官方文档中的教程和库参考也很重要。此外,实践练习和社区支持也是关键点,可以引用用户提到的社区和聊天机器人辅助编程的部分。需要确保每个步骤都有逻辑性,并且引用相关的资料。例如,在第一步推荐Wikibooks时,可以引用[^1]。在提到官方文档时,引用[^4]。社区支持和聊天机器人部分引用[^2]和[^5]。职业发展部分引用[^3]。然后,生成相关问题时要考虑用户可能遇到的后续问题,比如学习资源推荐、练习方法、调试技巧、进阶方向和应用场景。这些问题需要与回答内容相关,帮助用户深入探索。最后,检查格式是否正确,行内数学表达式和独立公式是否使用正确,引用标识是否自然添加。确保没有使用任何Markdown格式,代码块用三个反引号包裹,语言指定为python。同时,回答要口语化,符合思考过程的要求。</think>### Python编程学习指南(针对初学者) #### 第一步:选择结构化教程 建议从Wikibooks的Python教程开始,内容简明易懂,适合快速建立基础编程思维[^1]。例如: ```python # 第一个Python程序 print("Hello, World!") ``` #### 第二步:理解核心概念 重点关注以下内容: 1. 变量与数据类型:`$x = 5$` 2. 控制流:`if-else`/`for`/`while` 3. 函数定义:`def add(a, b): return a + b` 4. 列表操作:`$list = [1,2,3]$` #### 第三步:实践编码练习 通过实际项目巩固知识,例如: ```python # 计算斐波那契数列 def fibonacci(n): a, b = 0, 1 for _ in range(n): print(a) a, b = b, a+b ``` #### 第四步:利用官方文档 访问[Python官方文档](https://docs.python.org/3/),特别是: - 语言参考(语法规范) - 标准库指南(如`math`模块的`$sqrt()$`函数)[^4] #### 第五步:加入开发者社区 遇到问题时,可在Stack Overflow或Reddit的Python版块提问,全球开发者会提供解决方案[^2] #### 第六步:使用AI辅助工具 通过ChatGPT等工具进行交互式学习,例如询问: "如何用Python实现冒泡排序?" 可获得即时代码示例和解释[^2] #### 第七步:职业发展路径 根据引用[^3],建议学习方向: 1. Web开发(Django/Flask) 2. 数据分析(Pandas/NumPy) 3. 自动化脚本
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值