python对序列做切割,如list、str、bytes等。其实,凡是实现了__getitem__
和__setitem__
这个两个魔法方法的类都可以切割(后面会介绍)。序列的切割是通过序列的下标来进行切割,序列的下标从0开始,且可以是负数,如从后数,倒数第一个下标也可以是-1。
1.基本用法
基本写法:somelist[start:end]
表示从start开始一直取到end这个位置,但是不包括end位置本身的元素。且切片切出来的序列是一个新的序列,不会影响到原来的序列内容。
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[3:5]) # ['d', 'e']
print(a_list[1:7]) # ['b', 'c', 'd', 'e', 'f', 'g']
如果是从头开始切,就可以省略冒号左边的下标0,如果一直取到末尾,就可以省略右侧的下标。如下:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[:3]) # ['a', 'b', 'c']
print(a_list[5:]) # ['f', 'g', 'h']
使用负数作为下标,表示从列表的末尾开始往前数第几个元素。如下:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[-3:]) # ['f', 'g', 'h']
print(a_list[5:-2]) # ['f']
通过切片还可以实现列表复制。
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
b_list = a_list[:]
print(b_list)
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
2.切片索引越界
当我们使用切片操作时,如果索引越界:起点与终点的位置超出了列表本身的边界,那么系统会自动忽略不存在的元素。例如:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[:10]) # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[-10:]) # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
但是当我们用下标直接访问列表时,索引越界就会抛出异常。如下:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[10])
# IndexError: list index out of range
3.使用切片修改序列内容
切片操作可以出现在赋值符号左侧,表示用右侧的那些元素代替列表中切片内的元素。而且赋值符号两边个数元素不必相等。位于切片范围之外的元素保留,但是列表长度可能发生变化。
例子如下:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a_list[2:7] = [1, 2, 3]
print(a_list) # ['a', 'b', 1, 2, 3, 'h']
下面例子会使列表边长:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a_list[2:3] = [1, 2, 3]
print(a_list) # ['a', 'b', 1, 2, 3, 'd', 'e', 'f', 'g', 'h']
4.带步进切片
写法:somelist[start:end:step]
step表示切片的间隔,也就是从start开始取第一个元素,向后数,每隔step个元素,取下一个元素,直到end(不包含end)为止。例如:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[::2]) # ['a', 'c', 'e', 'g']
print(a_list[1:7:3]) # ['b', 'e']
步进step还可以是负数,表示从start开始取第一个元素,向前数,每隔step的绝对值个元素,取下一个元素,直到end(不包含end)为止。注意,如果start比end小,则取出来的就是空。如下:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[::-2]) # ['a', 'c', 'e', 'g']
print(a_list[7:1:-3]) # ['b', 'e']
print(a_list[1:7:-1]) # []
利用负步进值可以实现序列反转:
a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(a_list[::-1])
# ['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
str = "人生苦短,我学python"
print(str[::-1])
# nohtyp学我,短苦生人
建议:
实际应用中,尽量不要同时使用起止下标和步进值;
如果必须使用,尽量使用正的步进值;
除了-1外,尽量不要使用其他负数做步进值,否则代码会很难懂。
要点
- 切片尽量简单,如果从头开始,就省略起始下标0,如果选取序列到末尾,省略终止下标;
- 切片允许下标越界,不用担心序列长度不够;
- 切片在赋值符号左边可以实现修改序列内容;
- 切片可以指定步进值,但是尽量不要使用太复杂的切片,见上面的建议。