最简单的排序方法是使用排序(list) 函数,该函数接受一个列表并按排序顺序返回包含这些元素的新列表。原始列表不会发生变化。
a = [5, 1, 4, 3] print(sorted(a)) ## [1, 3, 4, 5] print(a) ## [5, 1, 4, 3]
最常见的是将列表传递到排序函数中,但事实上,它可以将任何类型的可迭代集合作为输入。旧版 list.sort() 方法是下文详述的替代方法。与 order() 相比,Sort() 函数似乎更易于使用,因此我建议使用另外一个 PLURAL()。
可以通过可选实参自定义 order() 函数。可选的 Sort() 参数有两种,即情形为排序方式,例如,排序方式为:排序方式为反向排序。
strs = ['aa', 'BB', 'zz', 'CC'] print(sorted(strs)) ## ['BB', 'CC', 'aa', 'zz'] (case sensitive) print(sorted(strs, reverse=True)) ## ['zz', 'aa', 'CC', 'BB']
使用 key= 进行自定义排序
对于更复杂的自定义排序,Sort() 接受可选的“key=”字段,用于指定在比较前会转换每个元素的“key=”函数。键函数接受 1 个值并返回 1 个值,返回的“proxy”值将用于排序中的比较。
例如,对于字符串列表,指定 key=len(内置的 len() 函数)可按长度对字符串进行排序(从最短到最长)。此排序方式会为每个字符串调用 len() 以获取代理长度值列表,然后使用这些代理值进行排序。
strs = ['ccc', 'aaaa', 'd', 'bb'] print(sorted(strs, key=len)) ## ['d', 'bb', 'ccc', 'aaaa']
再举一个例子,指定“str.lower”作为键函数,可以强制排序使大写和小写保持一致:
## "key" argument specifying str.lower function to use for sorting print(sorted(strs, key=str.lower)) ## ['aa', 'BB', 'CC', 'zz']
您也可以传入自己的 MyFn 作为关键函数,如下所示:
## Say we have a list of strings we want to sort by the last letter of the string. strs = ['xc', 'zb', 'yd' ,'wa'] ## Write a little function that takes a string, and returns its last letter. ## This will be the key function (takes in 1 value, returns 1 value). def MyFn(s): return s[-1] ## Now pass key=MyFn to sorted() to sort by the last letter: print(sorted(strs, key=MyFn)) ## ['wa', 'zb', 'xc', 'yd']
如需进行更复杂的排序,例如依次按姓氏和名字排序,您可以使用 itemgetter 或 attrgetter 函数,例如:
from operator import itemgetter # (first name, last name, score) tuples grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(1,0)) # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)] sorted(grade, key=itemgetter(0,-1)) #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]
sort() 方法
作为 order() 的替代方案,对列表的 order() 方法将该列表按照升序排序,如 list.sort()。sort() 方法会更改底层列表并返回 None,因此可按如下方式使用它:
alist.sort() ## correct alist = blist.sort() ## Incorrect. sort() returns None
以上是对 Sort()的一个非常常见的误解:它 *不会返回* 已排序的列表。必须对列表调用 sort()方法;该方法不适用于任何可枚举的集合(但上述 sort()函数适用于任何可枚举的集合)。order() 方法早于排序函数,因此您可能会在旧版代码中看到它。sort() 方法不需要创建新列表,因此,如果要排序的元素已位于列表中,其速度可能会快一些。
元组
元组是固定大小的元素分组,例如 (x, y) 坐标。元组与列表类似,只不过它们是不可变的,也不会更改大小(元组并非绝对不可变,因为所含元素之一可能是可变的)。元组在 Python 中扮演着一种“结构体”角色,可以方便地传递固定大小的逻辑值包。需要返回多个值的函数只需返回值的元组即可。例如,如果我想要一个 3-D 坐标列表,自然的 Python 表示形式就是元组列表,其中每个元组的大小为 3,包含一个 (x, y, z) 组。
要创建元组,只需用英文逗号分隔括号内的值即可。“空”元组只是一对空的圆括号。访问元组中的元素就像访问列表一样 - len()、[ ]、for、in 等都的工作方式相同。
tuple = (1, 2, 'hi') print(len(tuple)) ## 3 print(tuple[2]) ## hi tuple[2] = 'bye' ## NO, tuples cannot be changed tuple = (1, 2, 'bye') ## this works
要创建大小为 1 的元组,唯一的元素必须后跟英文逗号。
tuple = ('hi',) ## size-1 tuple
在语法中,这是一个有趣的情况,但为了区分元组和将表达式放在圆括号中的常见情况,必须使用逗号。在某些情况下,您可以省略圆括号,Python 会从逗号中看到您预期的元组。
将元组分配给大小相同的变量名称元组会分配所有相应的值。如果元组的大小不同,则会抛出错误。此功能也适用于列表。
(x, y, z) = (42, 13, "hike") print(z) ## hike (err_string, err_code) = Foo() ## Foo() returns a length-2 tuple
列表推导(可选)
列表推导是一项更高级的功能,在某些情况下很实用,但练习时并不需要,而且您一开始也不需要学习(例如,您可以跳过此部分)。列表推导是一种用于编写可扩展为完整列表的表达式的紧凑型方式。假设我们有一个列表 nums [1, 2, 3, 4],以下是要计算其平方数列表 [1, 4, 9, 16] 的列表理解:
nums = [1, 2, 3, 4] squares = [ n * n for n in nums ] ## [1, 4, 9, 16]
语法为 [ expr for var in list ]
- for var in list
看起来像一个常规的 for 循环,但没有冒号 (:)。系统会对每个元素计算一次左侧的 expr,从而给出新列表的值。以下是一个字符串示例,其中每个字符串都更改为大写并附加“!!!”:
strs = ['hello', 'and', 'goodbye'] shouting = [ s.upper() + '!!!' for s in strs ] ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']
您可以在 for 循环右侧添加 if 测试,以缩小结果范围。系统会为每个元素(包括只包括测试为 true 的元素)评估 if 测试。
## Select values <= 2 nums = [2, 8, 1, 6] small = [ n for n in nums if n <= 2 ] ## [2, 1] ## Select fruits containing 'a', change to upper case fruits = ['apple', 'cherry', 'banana', 'lemon'] afruits = [ s.upper() for s in fruits if 'a' in s ] ## ['APPLE', 'BANANA']
练习:list1.py
要练习本部分中的资料,请尝试稍后在 list1.py 中使用排序和元组的问题(在基本练习中)。