首页 > 编程知识 正文

pythonsort和sorted的区别,python如何使用sort函数

时间:2023-05-04 19:21:57 阅读:196973 作者:475

sort和sorted在python中常用语列表(或类列表)的排序,但是在python中有所区别。

他们的唯一的共同点恐怕就是都可以对列表排序,区别:

1. sorted是python的内置函数,可以对列表(list),元祖(tuple),字典(dict)和字符串(str)进行排序,排序对象作为sorted函数的参数,使用示例如下:

a_tuple =(1,3,2,4)

sorted(a_list)

(1,2,3,4) #返回

2. sort() 是列表类的方法,只能对列表排序。sorted()对列表排序时,有返回值;sorte()对列表排序时,无法返回值(直接在原列表中操作)。

a_list = [1,3,5,2]

a_list.sort() #执行后无法返回

a_list #再次访问a_list时,列表已经被排序

[1,2,3,5]

a_list = [1,3,5,2]

sorted(a_list) #执行后直接返回结果,不改变原来的列表

[1,2,3,5]

-----

sort 方法和 sorted 函数的异同

官方用法

sort 的用法:

sort(self, /, *, key=None, reverse=False)

Sort the list in ascending order and return None.

The sort is in-place (i.e. the list itself is modified) and stable (i.e. the

order of two equal elements is maintained).

If a key function is given, apply it once to each list item and sort them,

ascending or descending, according to their function values.

The reverse flag can be set to sort in descending order.

sorted 的用法:

Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)

Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the

reverse flag can be set to request the result in descending order.

相同点:

sort 和 sorted 都有两个可选仅限关键字参数 key 和 reverse,都是默认升序排序。

不同点:

1.sort 是列表的一个方法,它的第一个参数是 self,即列表实例对象本身;

sorted 是内置函数,它的第一个参数是 iterable,即可迭代对象。

所以 sorted 不止可以作用于列表,还可以作用于元组、字典等可迭代对象。

2.sort 方法是对列表原地排序,返回值是 None;

sorted 函数是返回一个新的列表,不改变原可迭代对象。

3.sort 方法不能级联调用,sorted 函数可以级联调用。

---

sort 方法和 sorted 函数的基本用法

方法(Method)和函数(Function),很多时候大多数人不区分方法和函数,基本当做一回事,这其实没啥问题。但是看 Python 官方文档的时候,有时候出现 Method 有时候又是 Function,让人很头疼,所以区分一下方法和函数还是有好处的。其实区分也比较简单。

方法(Method):是通过 obj.funcname() 来引用调用。

如:列表的 sort 方法,调用时就是 list.sort()。

函数(Function):是通过 funcname() 直接调用。

如内置函数(built-in function) sorted,调用时就是 sorted()。

注:Python API 的一个惯例(convention)是:

如果一个函数或者方法是原地改变对象,那么应该返回 None。

这么做的目的是为了告诉调用者对象被原地改变了。

这个约定的弊端是无法级联调用(cascade call)这些方法。

而返回新对象的方法可以级联调用,从而形成连贯的接口(fluent interface)。

sort 方法和 sorted 基本使用

list.sort():对列表进行原地(in place)排序,默认是升序,返回值是 None。

sorted():对可迭代对象进行排序,默认是升序,并把排序结果作为一个新的列表返回,原迭代对象顺序不受影响。

>>> list_a = [1, 5, 6, 4, 2, 3]

>>> sorted(list_a) # 返回一个新的排好序的 list

[1, 2, 3, 4, 5, 6]

>>> list_a # list_a 不改变

[1, 5, 6, 4, 2, 3]

>>> print(list_a.sort()) # list_a.sort() 就地排序,返回值是 None

None

>>> list_a # list_a 发生改变

[1, 2, 3, 4, 5, 6]

sorted 函数除了用于列表,还可用于其他可迭代对象,如元组、生成器等。

sorted((1, 5, 9, 2, 6, 8, 7)) # 对元组排序

[1, 2, 5, 6, 7, 8, 9]

sorted('afbcedh') # 对字符串排序

['a', 'b', 'c', 'd', 'e', 'f', 'h']

list(range(10,0,-1))

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

sorted(range(10,0,-1)) # 对生成器排序

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

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

[1, 2, 3, 4, 5]

降序可选仅限关键字参数 reverse

sort 方法和 sorted 函数都可以接收一个可选仅限关键字参数(keyword-only arguments) reverse,用于指定是升序(Ascending)还是降序(Descending)。

默认 reverse=False 即升序排序。

list_a = [3, 1, 2, 4]

sorted(list_a) # 默认升序

[1, 2, 3, 4]

sorted(list_a, reverse=True) # 降序排序

[4, 3, 2, 1]

list_a # list_a 不变

[3, 1, 2, 4]

list_a.sort() # 默认原地升序排序

list_a

[1, 2, 3, 4]

list_a.sort(reverse=True) # 原地降序排序

list_a

[4, 3, 2, 1]

注: 仅限关键字参数 即只能通过 keyword=value 的形式传参的参数叫仅限关键字参数,有关 Python 函数仅限关键字参数、仅限位置参数、可变参数、默认参数、位置参数、可变关键字参数等可以参看我的另一篇总结。一文了解Python函数

接下来我们介绍另一个更加强大的可选仅限关键字参数 key。

可选仅限关键字参数 key

sort 方法和 sorted 函数还可以接收一个可选仅限关键字参数 key,key 是一个只有一个参数的函数,这个函数会依次作用于序列的每一个元素,并将所得的结果作为排序的依据。key 默认是 None,即恒等函数(identity function),也就是默认用元素自己的值排序。

举栗子:

>>> list_a = ['This', 'is', 'a', 'test', 'string', 'from', 'Andrew']

>>> sorted(list_a, key=str.lower)

['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

>>> list_a

['This', 'is', 'a', 'test', 'string', 'from', 'Andrew']

这里的 key=str.lower 就是把 list_a 中的每个元素都用 str.lower 方法处理,即:都转为小写,然后再进行比较排序。

对于复杂的数据对象,我们可以用对象的索引,取对象的一部分作为比较的 key,这时匿名函数会帮助我们,举栗子:

>>> student_tuples = [

... ('john', 'A', 15),

... ('聪明的麦片', 'B', 12),

... ('dave', 'B', 10),

... ]

>>> sorted(student_tuples, key=lambda student: student[2]) # 根据年龄排序

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

我们还可以取对象的属性作为比较的 key,举栗子:

>>> 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('聪明的麦片', 'B', 12),

... Student('dave', 'B', 10),

... ]

>>> sorted(student_objects, key=lambda student: student.age) # 按年龄进行排序

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

可以看到 key 非常的强大!使得复杂的数据结构可以按照我们自己的意愿进行排序。

list.sort、sorted、max 和 min 中可选仅限关键字参数 key 的设计非常棒!使用 key 会更加高效且简洁。简单是指你只需要定义一个只有一个参数的函数,用于排序即可。高效是指 key 的函数在每个元素上只会调用一次,而双参数比较函数,则每次两两比较的时候都会被调用。(PS:这一点还不是特别理解)

operator 模块的使用

因为通过索引或者属性以及函数来排序非常常用,所以 Python 内置的 operator 模块提供了 itemgetter(), attrgetter() 和 methodcaller() 函数来更加简单而快速的实现相关的功能。

>>> from operator import itemgetter, attrgetter # 导入相关的函数

>>> sorted(student_tuples, key=itemgetter(2)) # 按索引取值排序

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

>>> sorted(student_objects, key=attrgetter('age')) # 按属性取值排序

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

此外,通过 operator 模块还可以轻松实现多级排序,比如上面的学生列表,先按成绩排序,再按年龄排序。

>>> sorted(student_tuples, key=itemgetter(1,2))

[('john', 'A', 15), ('dave', 'B', 10), ('聪明的麦片', 'B', 12)]

>>> sorted(student_objects, key=attrgetter('grade', 'age'))

[('john', 'A', 15), ('dave', 'B', 10), ('聪明的麦片', 'B', 12)]

sort 方法和 sorted 函数背后的排序算法

sorted 和 list.sort 背后的排序算法都是 Timsort 算法,它是一种自适应算法,会根据原始数据的特点交替使用归并排序(merge sort)和插入排序(insertion sort)。

在实际应用场景中这是非常有效的一种稳定排序算法。Timsort 在 2002 年开始在 CPython 中使用,2009 年起,开始在 Java 和 Android 中使用。

这里解释一下稳定排序算法,它指排序前和排序后,值相同的元素不交换位置。

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]

>>> sorted(data, key=itemgetter(0)) # 按照颜色排序

[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

可以看到原始序列是 (‘red’, 1) 在 (‘red’, 2)前面,排序后,因为 red 相同,二者不交换位置,(‘red’, 1) 依然在 (‘red’, 2)前面,这就叫做稳定排序。反之,如果交换了,就叫不稳定。

稳定排序非常重要,因为它可以让我们进行多步排序。

比如我们要实现对学生数据进行排序,要求是以成绩降序排列,如果成绩相同,则再按年龄升序排序。

那么我们可以通过两步实现:第 1 步是先以年龄升序排列,第 2 步再以成绩等级降序排列。注:按照算法,升序的话,B 的等级排在 A 后面。

代码如下:

>>> s = sorted(student_objects, key=attrgetter('age'))

>>> sorted(s, key=attrgetter('grade'), reverse=True)

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

上面就实现了成绩降序排序,成绩相同则年龄升序排序。上面的代码我们也可以整合到一行,要注意顺序:

>>> sorted(sorted(student_objects, key=attrgetter('age')), key=attrgetter('grade'), reverse=True)

[('dave', 'B', 10), ('聪明的麦片', 'B', 12), ('john', 'A', 15)]

Python 大多数排序(sort 方法和 sorted 函数)用的都是 Timsort 排序算法,它是一种混和的稳定排序算法,更多关于 Timsort 排序算法的知识可以参考学习Wiki Timsort

巨人的肩膀

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。