python range倒序_深入讨论Python中的序列切片语法

本小节深入探讨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编程基础及应用_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.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

​ 综上,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

​ 现以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

​ 当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编程基础及应用 — 重庆大学 高等教育出版社,作者亲授_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com

dd536c4690c5977fa8f0759863b03ea9.png
版权声明 本文 可以在互联网上自由转载,但必须:注明出处(作者:海洋饼干叔叔)并包含指向本页面的链接。 本文 不可以以纸质出版为目的进行改编、摘抄。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值