python4:序列概览

Python中的序列类型包括list、tuple、range、二进制数据、text和string,这里对序列的公共操作做一个介绍,后面将陆续介绍每一种序列类型。

公共序列操作

所有序列类型都可以近些某些特定的操作,包括:索引、分片、加、乘、计算序列长度、最大值、最小值等操作。

索引

序列中的每个元素被分配一个序号,第一个索引为0,第二个为1,依次类推。假定s是一个序列,s[i]即表示是的第i个元素,i大于0且小于s的长度,看下面的例子:

>>> s = ‘Hello‘
>>> s[0]
‘H‘
>>> ‘Hello‘[1]
‘e‘

s[i]中i也可以是负数,这是Python会从右边,也就是最后1个元素开始计数,最后一个元素的编号是-1(不是-0,因为那会和第1个元素重合),例如:

>>> ‘Hello‘[-1]
‘o‘
>>> ‘Hello‘[-4]
‘e‘

分片

分片操作可以访问一定范围内的元素,s[i:j]表示访问[i,j)范围的元素,例如:

>>> s = [1,2,3,4,5,6,7,8,9,10]
>>> s[3:6]
[4, 5, 6]

需要注意i包含在分片内,而j不包含在分片内。你也可以不指定开始和结尾,例如:

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

你同样可以使用负索引:

>>> s[-3:]
[8, 9, 10]

但需要注意的是,如果使用了索引-1,则最后一个元素无法访问,你只能使用上面的方法访问最后一个元素:

>>> s[-3:-1]
[8, 9]
>>> s[-3:0]
[]

你还可以指定步长,就是使用第3个参数:s[i:j:step],分片操作将按照这个步长便利序列的元素,然后返回开始和结束点之间的所有元素:

>>> s[0:10:2]
[1, 3, 5, 7, 9]
>>> s[1:10:2]
[2, 4, 6, 8, 10]

或者:

>>> s[::2]
[1, 3, 5, 7, 9]

步长可以为负,这时表示从右向左提取元素:

>>> s[8:3:-2]
[9, 7, 5]
>>> s[::-2]
[10, 8, 6, 4, 2]

序列加

假定序列s和t,s + t表示两个序列相加:

>>> [1,2,3] + [4,5,6]
[1, 2, 3, 4, 5, 6]
>>> ‘Hello. ‘ + ‘world!‘
‘Hello. world!

不同类型的序列相加将导致异常。需要注意如果序列为不可变序列,则序列相加的结果将是生成一个新的序列,将带来一定的代价。

乘法

序列s和数字n相乘,即s * n,会生成新的序列,在新的序列中,原来的序列被重复n次,例如:

>>> [42] * 5
[42, 42, 42, 42, 42]

注意空序列[] * n任然为空序列[],如果想生成一个长度为n的序列,可以用下面的方法:

>>> s = [None] * 10
>>> s
[None, None, None, None, None, None, None, None, None, None]

None是Python的内建值,表示“这里什么也没有”。
对于嵌套序列需要注意,看下面的例子:

>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]

出现这种结果的根本原因是lists的第2和3个元素和第1个元素引用的是同一个序列,如果要避免这种情况,可以使用下面的方法:

>>> lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]

in和not in

in运算符用于检查一个值是否在序列中,not in则这行相反的操作,两者的使用方法一致。下面是一些例子:

>>> s = ‘Hello‘
>>> ‘e‘ in s
True
>>> ‘ee‘ in s
False
>>> ‘ee‘ not in s
True
>>> lists = [‘mine‘,‘yours‘,‘his‘]
>>> input(‘This is ‘) in lists
This is mine
True

长度、最大值和最小值

假定s是一个序列,len(s)计算s的长度,min(s)返回s的最小值,max(s)返回s的最大值。

>>> numbers = [10,20,30]
>>> len(numbers)
3
>>> max(numbers)
30
>>> min(numbers)
10
>>> max(2,3,4)
4
>>> min(3,4,1,2)
1

index

s.index(x)返回x在s中第一次出现的位置。

>>> s = ‘Thank you!‘
>>> s.index(‘an‘)
2
>>> [1,2,3,4].index(3)
2

你也可以使用s.index(x,i)指定起始位置。

>>> s *= 2
>>> s
‘Thank you!Thank you!‘
>>> s.index(‘an‘)
2
>>> s.index(‘an‘,4)
12

还可以使用s.index(x,i,j)同时指定起始和结束位置。

>>> numbers = [1,2,3] * 3
>>> numbers
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> numbers.index(2)
1
>>> numbers.index(2,5,8)
7

需要注意的是如果x不在s中的[i,j)返回内,将抛出ValueError,例如下面的例子:

>>> numbers.index(2,5,7)
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    numbers.index(2,5,7)
ValueError: 2 is not in list
>>> s.index(‘an‘,14)
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    s.index(‘an‘,14)
ValueError: substring not found

count

s.count(x)返回x在s中出现的次数。

>>> s = ‘Thank you!‘
>>> s *= 5
>>> s
‘Thank you!Thank you!Thank you!Thank you!Thank you!‘
>>> s.count(‘an‘)
5
>>> s.count(‘aaa‘)
0

不可变序列

仅有的在不可变序列中实现而没在可变序列中实现的操作是hash()方法,这样就允许不可变序列,例如tuple,被用于字典的key和存储在set中。
注意尝试哈希一个包含不可哈希值的不可变队列将导致TypeError。

可变队列

可变队列支持队列的添加、删除和修改操作。

赋值

可以使用索引标记来为某个元素赋值,例如:

>>> s = [1,1,1]
>>> s[1] = 2
>>> s
[1, 2, 1]

对不存在的元素进行复制,将导致IndexError。

>>> s[3] = 4
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    s[3] = 4
IndexError: list assignment index out of range

可以s[i:j]=t对某个区间进行赋值,t必须是一个迭代器。

>>> s *= 3
>>> s
[1, 2, 1, 1, 2, 1, 1, 2, 1]
>>> s[2:5] = [10,10,10]
>>> s
[1, 2, 10, 10, 10, 1, 1, 2, 1]
>>> other = [3] * 5
>>> s[:4] = other
>>> s
[3, 3, 3, 3, 3, 10, 1, 1, 2, 1]
>>> s[-5:] = other
>>> s
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]

你甚至可以指定赋值的步长。

>>> s = [1] * 10
>>> s[2:9:2] = [5,6,7,8]
>>> s
[1, 1, 5, 1, 6, 1, 7, 1, 8, 1]

前面讲到的分片的技巧在这里都可以使用。

删除元素

使用del语句来删除序列中的元素,del可以删除单个元素,也可以删除区间数据,如下:

>>> names = [‘Alice‘,‘Beth‘,‘Cecil‘,‘Dee-Dee‘,‘Earl‘]
>>> del names[2]
>>> names
[‘Alice‘, ‘Beth‘, ‘Dee-Dee‘, ‘Earl‘]
>>> del names[1:3]
>>> names
[‘Alice‘, ‘Earl‘]

del操作也可以指定步长。

>>> names = [‘Alice‘,‘Beth‘,‘Cecil‘,‘Dee-Dee‘,‘Earl‘]
>>> del names[::2]
>>> names
[‘Beth‘, ‘Dee-Dee‘]

del也能用于字典元素甚至是其他变量的删除操作,在后面介绍。

append和pop

append用于添加元素到序列的结尾,pop则是从序列中移除一个元素。下面看append的操作:

>>> s = [1,2,3]
>>> s.append(4)
>>> s
[1, 2, 3, 4]

pop(i)中i的默认值为-1,因此默认移除最后一个元素,并返回移除的元素的值:

>>> s.pop()
4
>>> s
[1, 2, 3]
>>> s.pop(1)
2
>>> s
[1, 3]

注意append和pop只是在恰当位置修改原来的列表。

insert

insert(i,x)用于将x插入到序列指定的位置:

>>> s = [1,2,3,4,5,6,7,8,9,10]
>>> s.insert(5,‘error‘)
>>> s
[1, 2, 3, 4, 5, ‘error‘, 6, 7, 8, 9, 10]

insert方法可以使用分片赋值来实现:

>>> s = [1,2,3,4,5,6]
>>> s[3:3] = [‘error‘]
>>> s
[1, 2, 3, ‘error‘, 4, 5, 6]

这样的后果就是可读性不如insert更好。

extend

extend(t)使用t来扩展序列s,t是另一个序列,即使用新序列来扩展原有的序列:

>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6]

这个操作很像a+b的操作,但extends修改了被扩展的序列,即a,而a+b的操作则是返回一个全新的列表,a和b都没有被改变,因此a+b的效率会比extend的效率低。
我们也可以使用分片赋值来实现相同的结果:

[1, 2, 3, 4, 5, 6]
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a[len(a):] = b
>>> a
[1, 2, 3, 4, 5, 6]

同样,这样的可读性不如extend更好。

remove

remove(x)移除序列中x的第一个匹配项。

>>> s = [1,2,3] * 3
>>> s.remove(2)
>>> s
[1, 3, 1, 2, 3, 1, 2, 3]

只有第一个出现的值被移除了,如果移除的值不在序列中,则抛出ValueError异常。

>>> s.remove(4)
Traceback (most recent call last):
  File "<pyshell#86>", line 1, in <module>
    s.remove(4)
ValueError: list.remove(x): x not in list

remove也是一个原位置改变方法,无返回值。

clear

clear()移除序列中的所有元素。

>>> s = [1,2,3] * 3
>>> s.clear()
>>> s
[]

也可以使用del操作来达到clear的效果,但可读性不如clear:

>>> s = [1,2,3] * 3
>>> del s[:]
>>> s
[]

copy

copy()创建一个序列的浅拷贝。

>>> s  = [1,2,3,4,5,6]
>>> c = s.copy()
>>> c.append(7)
>>> s
[1, 2, 3, 4, 5, 6]
>>> c
[1, 2, 3, 4, 5, 6, 7]

但需要注意只是浅拷贝,看下面的例子:

>>> s = [[1],[2],[3]]
>>> c = s.copy()
>>> c[1].append(5)
>>> c
[[1], [2, 5], [3]]
>>> s
[[1], [2, 5], [3]]

由于只是浅拷贝,c中元素和s中元素指向的是相同的序列,因此导致这样的结果。

reverse

reverse()方法将队列中的元素反向存放,该方法改变列表不返回值。

>>> s = [1,2,3]
>>> s.reverse()
>>> s
[3, 2, 1]

小结

到这里,序列的基本操作就介绍完毕了,这些基本操作是序列的基础,后面介绍的序列类型都可使用这些操作(区分不可变序列和可变序列)。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。