本小节深入探讨Python中的序列切片语法。 切片-slicing可以获取序列的子序列(列表,字符串...):
numbers = [x for x in range(10)]
print("numbers:",numbers)
print("numbers[3:9]:",numbers[3:9])
print("numbers[3:]:",numbers[3:])
print("numbers[:9]:",numbers[:9])
print("numbers[-6:-1]:",numbers[-6:-1])
print("numbers[1:9:2]:",numbers[1:9:2])
print("numbers[-1:1:-2]:",numbers[-1:1:-2])
本文节选自作者的《Python编程基础及应用》视频教程。
Python编程基础及应用_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili.com切片
切片-slicing可以获取序列的子序列(列表,字符串...):
numbers = [x for x in range(10)]
print("numbers:",numbers)
print("numbers[3:9]:",numbers[3:9])
print("numbers[3:]:",numbers[3:])
print("numbers[:9]:",numbers[:9])
print("numbers[-6:-1]:",numbers[-6:-1])
print("numbers[1:9:2]:",numbers[1:9:2])
print("numbers[-1:1:-2]:",numbers[-1:1:-2])
执行结果:
numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
numbers[3:9]: [3, 4, 5, 6, 7, 8]
numbers[3:]: [3, 4, 5, 6, 7, 8, 9]
numbers[:9]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
numbers[-6:-1]: [4, 5, 6, 7, 8]
numbers[1:9:2]: [1, 3, 5, 7]
numbers[-1:1:-2]: [9, 7, 5, 3]
![759325c7b2ac80ee999b1669a478099b.png](https://i-blog.csdnimg.cn/blog_migrate/727d6feeca4b97fa5f05da5537860518.jpeg)
综上,numbers的切片的完整形式为: numbers[x:y:z],z为步长,缺省值为1,x为起始下标,y为终止下标。z > 0时,x缺省为0, 包括最左端的元素, y缺省为len(numbers),包括最右端的元素,最右端元素的下标为len(numbers)-1。注意,当z值为负数时,切片方向为从右往左,起始下标x应包括最右方(也就是最后一个)元素,故x的缺省值为len(numbers)-1;终止下标y则为-1, 这有点让有费解:因为如果y为0的话,列表的下标0元素将不会被包括在切片中。如果你还感到疑惑,请看下一小节。
深入理解切片
切片的过程事实上跟数值列表range(x,y,z)的计数过程十分类似,由于这个切片过程适用于所有序列(字符串,列表...),故下图中我们用seq[x:y:z]表示序列及其切片参数,首先考虑z>0的情况:
![da14e18282471e62792c04ab49feba2a.png](https://i-blog.csdnimg.cn/blog_migrate/321f7c4a455b02c44680dca581e15259.png)
现以numbers[1:9:2]为例,依上述流程图说明输出集合为什么是[1,3,5,7]。首先,下标取值x=1,然后开始循环:
- 下标1 < 9成立,复制numbers[1],即值1;
- 下标=1+2=3;
- 下标3 < 9成立,复制numbers[3],即值3;
- 下标=3+2=5;
- 下标5 < 9成立,复制numbers[5],即值5;
- 下标=5+2=7;
- 下标7 < 9成立,复制numbers[7],即值7;
- 下标=7+2=9;
- 下标9 < 9不成立,循环结束。
如果你有C/C++经验,看下面的代码秒懂,因为Python的解释器就是用C/C++编写的。
for (int i=x;i<y;i+=z){
copy(seq[i]);
}
当z<0时,seq[x:y:z]的切片流程图如下:
![a29829672eaf1e27e0b693b0d9cfb264.png](https://i-blog.csdnimg.cn/blog_migrate/62423ca73818e8e2f65adf9780228047.png)
当z<0时,切片过程事实上是从序列尾部往头部方向行进的,由于z是负数,所以下标=下标+z事实上导致下标减小。如果你有C/C++经验,看下面的代码秒懂,因为Python的解释器就是用C/C++编写的。
for (int i=x;i>y;i+=z){
copy(seq[i]);
}
该你了,请依上述流程图,人肉执行numbers[-1:1:-2]的切片过程,看看输出结果跟Python解释器输出是否一致。提示,-1表示倒数第1个元素,即len(numbers)-1=9。
妙用切片
numbers = [x for x in range(10)]
numbersCopy = numbers[:]
print("id:", id(numbers), numbers)
print("id:", id(numbersCopy), numbersCopy)
numbersReversed = numbers[::-1]
print("numbersReversed:",numbersReversed)
numbers[3:5] = 77,88
print("numbers:",numbers)
执行结果:
id: 2611651371592 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
id: 2611651371656 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
numbersReversed: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
numbers: [0, 1, 2, 77, 88, 5, 6, 7, 8, 9]
从上述代码及执行结果可以看出,numbers[:]产生了numbers的副本,其效果等价于numbers.copy(), numbers与numbersCopy的id值不同;而numbers[::-1]从尾部往前进行切片,其切片正好将序列倒序。这与numbers.reverse()有区别,numbers.reverse()会导致numbers列表被改变,且不会返回新列表;而numbers[::-1]会保持numbers列表不变,并生成一个新的列表。
请注意倒数第二行代码,对列表的切片还可以用于批量修改列表元素。从结果可见,numbers[3:5] = 77,88等价于numbers[3] = 77和numbers[4] = 88。
字符串切片
作为一种序列,字符串的切片方法与列表几乎完全相同,见下述代码:
numbers = '0123456789'
print(numbers[2:5])
print(numbers[1:9:2])
print(numbers[:3:-2])
执行结果:
234
1357
975
本文节选自作者的B站MOOC及同名教材:
Python编程基础及应用 — 重庆大学 高等教育出版社,作者亲授_哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliwww.bilibili.com![dd536c4690c5977fa8f0759863b03ea9.png](https://i-blog.csdnimg.cn/blog_migrate/ae2112f43677f41e754f8f23607d37b3.jpeg)
版权声明 本文 可以在互联网上自由转载,但必须:注明出处(作者:海洋饼干叔叔)并包含指向本页面的链接。 本文 不可以以纸质出版为目的进行改编、摘抄。