Python 排序——sorted 与 sort 用法 (四)

使用.sort() 排序值

名称相似的.sort()与 sorted() 内置函数有着很大的不同。虽然它们或多或少都可以完成相同的事情,但 list.sort()的 help() 文档突出显示了.sort()和 sorted() 之间最重要的两个区别:

>>> # Python2
Help on method_descriptor:

sort(...)
    L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
    cmp(x, y) -> -1, 0, 1

>>> # Python3
>>> help(list.sort)
Help on method_descriptor:

sort(...)
    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*

首先,sort 是列表类的一种方法,只能与列表一起使用。它不是传递给它的迭代的内置函数。 其次,sort 返回 None 并修改值。我们来看看代码中这两种差异的影响:

>>> values_to_sort = [5, 2, 6, 1]
>>> # 尝试调用像使用sorted()调用sort()
>>> sort(values_to_sort)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sort' is not defined

>>> # 尝试在一个元组上使用 .sort()
>>> tuple_val = (5, 1, 3, 5)
>>> tuple_val.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'sort'

>>> # 排序列表并且赋值给新的变量
>>> sorted_values = values_to_sort.sort()
>>> print(sorted_values)
None

>>> # 打印原始变量
>>> print(values_to_sort)
[1, 2, 5, 6]

与此代码示例中的 sorted()相比,sort() 操作的方式有一些非常显着的差异:

1. sort() 不产生有序输出,因此对新变量的赋值仅传递 None 类型。

2. values_to_sort 列表已就地更改,并且不以任何方式维持原始顺序。

这些差异使得.sort()和 sorted() 绝对不能在代码中互换,如果以错误的方式使用它们,它们会产生意想不到的结果。

.sort()具有相同的 key 和 reverse 可选关键字参数,这些参数产生与 sorted() 相同的强大功能。在这里,可以按第三个单词的第二个字母对短语列表进行排序,然后反向返回列表:

>>> phrases = ['when in rome', 
...     'what goes around comes around', 
...     'all is fair in love and war'
...     ]
>>> phrases.sort(key=lambda x: x.split()[2][1], reverse=True)
>>> phrases
['what goes around comes around', 'when in rome', 'all is fair in love and war']

何时使用 sorted 和.sort?

我们已经看到了 sorted()和.sort() 之间的区别,但我们什么时候使用?该使用哪个?

假设有一场 5k 比赛即将举行:第一届年度 Python 5k。需要获取和分类来自比赛的数据,参赛者的号码和完成比赛所需的秒数:

>>> from collections import namedtuple

>>> Runner = namedtuple('Runner', 'bibnumber duration')

当参赛者越过终点线时,每个参赛者将被添加到名为参赛者的列表中。在 5k 比赛中,并非所有参赛者同时越过起跑线,所以第一个越过终点线的人可能实际上不是最快的人:

>>> runners = []
>>> runners.append(Runner('2528567', 1500))
>>> runners.append(Runner('7575234', 1420))
>>> runners.append(Runner('2666234', 1600))
>>> runners.append(Runner('2425234', 1490))
>>> runners.append(Runner('1235234', 1620))
>>> # Thousands and Thousands of entries later...
>>> runners.append(Runner('2526674', 1906))

每次参赛者越过终点线时,他们的号码号和他们的总持续时间(以秒为单位)都会添加到跑步者。

现在,负责处理结果数据的尽职程序员看到了这个列表,知道前 5 名最快的参与者是获得奖品的获胜者,剩下的参赛者将按最快的时间进行排序。

赛事中没有提到通过不同属性进行多类型的排序要求,也没有提到将列表在某处存储,只需按持续时间排序并获取持续时间最短的五个参与者:

>>> runners.sort(key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners[:5]

在这个带有 sorted() 的场景中,原始的参赛者列表仍然完好无损并且没有被覆盖,并且每三十七人越过终点线的即兴要求可以通过与原始值互动来完成:

>>> every_thirtyseventh_runners = runners[::37]

结论:** 如何在 Python 中排序

.sort()和 sorted() 都可以准确地提供排序功能,但在输出和修改时,两者都具有非常不同的特性,因此请确定是否要在应用程序中使用.sort(),因为它不可撤销地覆盖数据。