Manual
Return a new sorted list from the items in iterable.
Has two optional arguments which must be specified as keyword arguments.
key specifies a function of one argument that is used to extract a comparison key from each list element: key=str.lower. The default value is None (compare the elements directly).
reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.
Use functools.cmp_to_key() to convert an old-style cmp function to a key function.
The built-in sorted() function is guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal — this is helpful for sorting in multiple passes (for example, sort by department, then by salary grade).
For sorting examples and a brief sorting tutorial, see Sorting HOW TO.
直译
根据iterable中的项返回一个新排序的列表。
这里有两个可选参数,其必须指定为关键字参数。
- key指定某个参数的函数,它可以用于从每个列表元素中提取比较键,例如key=str.lower。默认值为None(直接比较元素)。
- reverse是一个布尔值,如果设置为True,列表的元素会将每个比较反置进行排列。
内建sorted()函数可以保证稳定,如果它保证不改变元素的相对顺序,那么排序就是稳定的。相对顺序的比较恒等,对于多次传递下的排序很有用(例如:按部门排序,然后按工资等级排序)
实例
实例摘自官方手册
基本排序
# 简单排序
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
# list.sort()方法,该方法仅对列表定义。
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
# sorted()支持任何迭代形式
>>> sorted({
1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
key函数
list.sort()和sorted()都有key参数,用来指定一个函数,并对每个列表元素对象调用该函数进行比较。
# 小写字符串比较,key=str.lower
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key参数的值应该是一个函数,其获取一个单独的参数,并返回一个用于排序目的键。这个技术执行速度快,因为每个输入记录只调用一次key函数。
常见模式式排序复杂对象,会使用一些对象的索引作为键,例如:
>>>
>>> student_tuples = [
... ('john', 'A', 15),
... ('jane', 'B', 12),
... ('dave', 'B', 10),
... ]
>>> sorted(student_tuples, key=lambda student: student[2])
# 依照年龄排序
[('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)
# 依照年龄排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
operator模块函数
上面展示的是很常见的key函数模式,因此Python提供了便捷的函数来使访问器函数更简单、更迅速,operator模块有itemgetter()、attrgetter()和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)]
operator模块函数允许多层级排序,例如,先按等级排序,然后按年龄:
>>>
>>> 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)]
升序和降序
list.sort()和sorted()都接受reverse参数(布尔值),这用于标识降序排序,例如:以反向年龄顺序获取学生数据:
>>>
>>> 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)]
排序稳定性和复杂排序
排序可以保证稳定性,这意味着如果多个记录具有相同的键,它们原来的顺序是受保护的。
>>>
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
注意两条blue记录保持了它们原有的顺序,即(‘blue’, 1) 是确保在(‘blue’, 2)之前的。
这条神奇的属性可以让你在一系列的排序级内建立复杂排序,例如:以年级降序排列学生数据,然后升序排列年龄。因此先做年龄排序,然后再使用年级排序:
>>>
>>> s = sorted(student_objects, key=attrgetter('age'))
# 以第二个键排序
>>> sorted(s, key=attrgetter('grade'), reverse=True)
# 现在以第一个键降序排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
Python的多重排序使用了Timsort算法,感兴趣的同学可以自行查找资料。
其他
- 对于本地化识别的排序,为key函数使用locale.strxfrm(),或为比较函数使用locale.strcoll()。
- reverse参数仍然可以保持排序的稳定性(因此同等键的记录可以保持原始顺序)。有趣的是,可以通过使用内建reversed()函数两次来模拟这个效果:
>>>
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> standard_way = sorted(data, key=itemgetter(0), reverse=True)
>>> double_reversed = list(reversed(sorted(reversed(data), key=itemgetter(0))))
>>> assert standard_way == double_reversed
>>> standard_way
[('red', 1), ('red', 2), ('blue', 1), ('blue', 2)]
- 当在两个对象间进行比较时,排序程序会使用\ lt(),因此定义一个\ lt()方法将一个标准排列顺序添加到类中,会使排序变得简单:
>>>
>>> Student.__lt__ = lambda self, other: self.age < other.age
>>> sorted(student_objects)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
- Key函数不需要直接依赖排序的对象,它也可以访问外部资源。例如:如果对字典中学生年级排序,它们可以用分离的学生名列表排列。
>>>
>>> students = ['dave', 'john', 'jane']
>>> newgrades = {
'john': 'F', 'jane':'A', 'dave': 'C'}
>>> sorted(students, key=newgrades.__getitem__)
['jane', 'dave', 'john']
拓展阅读
operator
itemgetter()
attrgetter()
methodcaller()
locale.strxfrm()
locale.strcoll()
reversed()