通用的序列操作¶
Python 内置了多种序列,其中最常用的是:列表、元组和字符串(字符串就是由字符组成的序列)。
列表和元组的主要不同在于,列表是可以修改的,而元组不可以修改。在编写程序时,几乎所有情况下都可使用列表来代替元组,一种例外情况是作为字典的键时只能是元组而不能是列表,因为字典的键是不可变的。
通用的序列操作包括索引、切片、相加、相乘和成员资格检查等。另外,Python 还提供了一些内置函数,可用于确定序列的长度以及找出序列中最大和最小的元素等。
序列索引¶
序列中的所有元素都有编号(从 0 开始递增),这称为索引(indexing),你可使用索引来获取元素。这种索引方式适用于所有序列。当你使用负数索引时,Python 将从右(即从最后一个元素)开始往左数,因此 -1 是最后一个元素的位置。你可像下面这样来访问各个元素:
>>> greet = 'Hello World'
>>> greet[0]
'H'
>>> greet[-1]
'd'
所有的序列都可直接对其执行索引操作,无需先将其赋值给变量。这与先赋值给变量再对变量执行索引操作是一样的。如果函数调用返回一个序列,可直接对其执行索引操作。
>>> 'Hello'[1]
'e'
>>> fourth = input('Year: ')[3]
Year: 2019
>>> fourth
'9'
序列切片¶
除使用索引来访问单个元素外,还可使用切片(slicing)来访问特定范围内的元素。切片适用于提取序列的一部分,其中的编号非常重要,第一个索引指定的元素包含在切片内,但第二个索引指定的元素不包含在切片内。请看下面的示例:
>>> greet = 'Hello World'
>>> greet[2:5]
'llo'
>>> greet[3:-2]
'lo Wor'
>>> greet[0:1]
'H'
Note
切片值与原序列的类型是相同的,列表的切片值是列表,字符串的切片值是字符串。即使切片只提取一个元素,仍将如此,在调用切片时请格外注意!
绝妙的简写¶
假设要截取列表中的最后三个元素,第二个索引值必须大于列表中元素的总数,才可以提取到最后一个元素,虽然它并不存在,但这种方法确实可以达到目的。
>>> greet[8:11]
'rld'
如果使用负数索引,索引值 -1 无法包含最后一个元素。如果使用索引0,即到达列表末尾后再前进一步,结果将如何呢?
>>> greet[-3:-1]
'rl'
>>> greet[-3:0]
''
结果并不理想。事实上,执行切片操作时,如果第一个索引指定的元素位于第二个索引指定的元素后面(如上例),结果就为空序列。
Note
在使用负数索引作为开始索引时,在极个别的情况下,会出现奇怪的结果。例如,当索引为 -0 时,也会返回原序列。
>>> greet = 'Hello World'
>>> greet[-0:]
'Hello World'
切片提供了一种什么都不写的简写方式,实现提取到最后一个元素的操作。如果切片结束于序列末尾,可省略第二个索引。如果切片开始于序列开头,也可省略第一个索引。
>>> greet[-3:]
'rld'
>>> greet[:3]
'Hel'
# 要复制整个序列,可将两个索引都省略
>>> greet[:]
'Hello World'
更大的步长¶
切片操作实际上有三个参数,但通常会省略第三个参数,即步长参数。默认为 1,这意味着从一个元素移到下一个元素,因此切片包含起点和终点之间的所有元素。还可以指定步长,如果指定的步长大于 1,将跳过一些元素。例如:步长为 2 时,将从起点和终点之间每隔一个元素提取一个元素。
>>> greet[0:11:1]
'Hello World'
>>> greet[0:11:2]
'HloWrd'
>>> greet[0:11:3]
'HlWl'
>>> greet[::4]
'Hor'
步长不能为 0,否则无法向前移动,但可以为负数,即从右向左提取元素。在这种情况下,要正确地提取元素颇费思量。此时,第一个索引依然包含在内,而第二个索引不包含在内。步长为负数时,第一个索引必须比第二个索引大。当省略起始和结束索引时,步长为正数时,它从起点移到终点,当步长为负数时,它从终点移到起点。
>>> greet[0:11:-2]
''
# 切片值依然不会提取结束索引位置的元素
>>> greet[11:0:-1]
'dlroW olle'
>>> greet[11:0:-2]
'drWol'
>>> greet[::-3]
'dooe'
>>> greet[5::-2]
' le'
>>> greet[:5:-2]
'drW'
序列相加¶
可使用加法运算符来拼接相同类型的序列。但是不能拼接列表 + 字符串。
>>> 'Hello ' + 'World'
'Hello World'
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> [1, 2, 3] + 'World'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
序列相乘¶
将序列与数字相乘时,将重复这个序列 n 次来创建一个新序列:
>>> 'Hello ' * 5
'Hello Hello Hello Hello Hello '
>>> [6] * 3
[6, 6, 6]
成员资格¶
运算符 in 检查指定的对象是否是序列的成员(即其中的一个元素),并返回相应的值:满足时返回 True;不满足时返回 False。
>>> greet = 'Hello World'
>>> 'H' in greet
True
>>> "Wor" in greet
True
>>> 'a' in greet
False
>>> 'llo ' in greet
True
# 开头添加了空格
>>> ' llo ' in greet
False
>>> numbers = [1, 2, 3, 4, 5, 6, 7]
>>> 2 in numbers
True
# 不能检查切片是否包含在序列中
>>> [2, 3] in numbers
False
查找元素的次数、元素的索引¶
count 和 index 都是序列的方法,count 用于统计某个元素在列表中出现的次数,index 从序列中查找指定值第一次出现的索引。
>>> greet = 'Hello World'
>>> greet.count('l')
3
>>> greet.index('l')
2
>>> greet.index('o')
4
长度、最小值和最大值¶
内置函数 len 返回序列中所包含的元素总数,而 min 和 max 分别返回序列中最小和最大的元素。
>>> numbers = [100, 34, 678]
>>> len(numbers)
3
>>> max(numbers)
678
>>> min(numbers)
34
>>> max(2, 3)
3
>>> min(9, 3, 2, 5)
2
序列解包¶
一次给多个变量赋值的方法,称为序列解包,但是需保证赋值运算符左右两边的元素数目相等。
>>> a, b, c = (1, 2, 3)
>>> a
1
>>> b
2
>>> c
3
序列解包还可以利用 * 表达式将多个元素赋值给一个变量(获取的值默认为 list)。
# 获取剩余部分
>>> a, b, *c = 0, 1, 2, 3
>>> a
0
>>> b
1
>>> c
[2, 3]
# 获取中间部分
>>> a, *b, c = 0, 1, 2, 3
>>> a
0
>>> b
[1, 2]
>>> c
3
# 如果左值比右值多,带 * 的变量默认为空
>>> a, b, *c = 0, 1
>>> a
0
>>> b
1
>>> c
[]
>>> a, *b, c = 0, 1
>>> a
0
>>> b
[]
>>> c
1
# 嵌套解包
>>> (a, b), (c, d) = (1, 2), (3, 4)
>>> a
1
>>> b
2
>>> c
3
>>> d
4
>>> a, b, c, d
(1, 2, 3, 4)