slice(切片)

在Python中,切片(slice)是对序列型对象(如liststringtuple)的一种高级索引方法。普通索引只取出序列中一个下标对应的元素,而切片取出序列中一个范围对应的元素,这里的范围不是狭义上的连续片段。

切片的基本语法为:

object[start_index : end_index : step]

如果没有缺省的话,表达式应该包含三个参数以及两个冒号,三个参数的意义分别如下:

1、start_index:切片的起始位置(包括该位置),0表示从第一个开始,1表示从第二个开始,以此类推。-1表示从倒数第一个开始,-2表示从倒数第二个开始,以此类推。缺省时取0或-1(即step为正数取0,负数取-1)

a=[9,2,8,7,4,5,1,5,6,8] 
a[0::]表示从第一个到最后一个,结果为   #[9,2,8,7,4,5,1,5,6,8]
a[1::]表示从第二个到最后一个          #[2,8,7,4,5,1,5,6,8]
a[-1::]表示从最后一个到最后一个,一共取一个值  #[8]

 2、end_index:切片的结束位置(!!!且不包括该位置),0表示第一个为终点,1表示第二个为终点,以此类推。-1表示倒数第一个为终点,-2表示倒数第二个为终点,以此类推。缺省时默认为序列长度(step为正数取正,step负数取负)

a=[9,2,8,7,4,5,1,5,6,8]
a[:0:]表示从第一个到第一个,一共取0个值      #[]
a[:1:]表示从第一个到第二个且不包括第二个     #[9]
a[:-1:]表示从第一个到最后一个且不包括最后一个,一共取9个值      #[9,2,8,7,4,5,1,5,6]
a[:8]表示从第一个到第九个且不包括第九个      #[9, 2, 8, 7, 4, 5, 1, 5]

 3、step,表示步长。可取正负数,正数表示从左往右,负数表示从右往左。缺省时取1

a=[9,2,8,7,4,5,1,5,6,8]
a[::1]表示从第一个到最后一个,步长为1      #[9,2,8,7,4,5,1,5,6,8]
a[::-1]表示从最后一个到第一个,步长为1       #[9,6,5,1,5,4,7,8,2,9]
a[::2]表示从第一个到最后一个,步长为2         #[9,8,4,1,6]

只有一个冒号时默认step为1。当start_index的位置在end_index的左边时,表示从左往右取值;当start_index的位置在end_index的右边时,表示从右往左取值 

>>> a = list(range(10))
 >>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[:5]
 [0, 1, 2, 3, 4]
 >>> a[5:]
 [5, 6, 7, 8, 9]
 >>> a[2:8]
 [2, 3, 4, 5, 6, 7]
 >>> a[::2]
 [0, 2, 4, 6, 8]
 >>> a[::-1]
 [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

基本索引

我们从Python的基本索引开始,即单个整数的索引。假设被索引的序列仍为之前提到的a,则基本索引的语法为a[index],其中index为下标。读者可能会觉得这里过于简单,但我们要强调的是Python一个语法糖:负数下标索引,即:index可以取为负数,当其为-n时,对倒数第n个元素进行索引。我们用一张表格值观展示a的索引范围。

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(li[1])
# 2
print(li[9])
# 10
print(li[-5])
# 6

非负下标索引和负数下标索引共同构成了Python索引的有效范围:​。有效范围的概念对切片的理解非常重要,在基本索引中,索引超出有效范围时会抛出IndexError异常:

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[10]
 Traceback (most recent call last):
   File "", line 1, in 
 IndexError: list index out of range
 >>> a[-11]
 Traceback (most recent call last):
   File "", line 1, in 
 IndexError: list index out of range

但在切片中不是这样。

简单切片

简单切片指的是这样的切片形式:a[start:stop],其行为是得到下标在这样一个前闭后开区间范围内的元素,其中startstop为负数时,简单看作是负数下标对应的位置即可:

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[2:3]
 [2]
 >>> a[5:9]
 [5, 6, 7, 8]
 >>> a[5:-1]
 [5, 6, 7, 8]
 >>> a[-5:9]
 [5, 6, 7, 8]
 >>> a[-5:-1]
 [5, 6, 7, 8]

事情到这里也很简单,下面着重讲解两个比较特殊的情况:超出有效索引范围缺省

超出有效索引范围 

startstop超出上文提到的有效索引范围​时,切片操作不会抛出异常,而是进行截断。可以这样去理解截断机制:我们假象把索引范围扩充到全体整数,只不过小于​或大于​的区域对应空元素,在这个扩充后的数轴上进行切片,只需把最终结果中的所有空元素忽略即可。

来看几个具体的例子:

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[-100:5]
 [0, 1, 2, 3, 4]
 >>> a[5:100]
 [5, 6, 7, 8, 9]
 >>> a[-100:100]
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[100:1000]
 []

另外,如果start的位置比stop还靠后怎么办?Python还是不会抛出异常,而是直接返回空序列:

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

缺省

startstop都是可以缺省的,在缺省的情况下,Python的行为是尽可能取最大区间,具体来说:

按照扩充索引范围的观点,start的缺省值是无穷小(​)stop的缺省值是无穷大(​)

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[:5]
 [0, 1, 2, 3, 4]
 >>> a[5:]
 [5, 6, 7, 8, 9]
 >>> a[100:]
 []

扩展切片

早期的Python解释器仅支持上述a[start:stop]形式的基本切片,后来加入了下面要介绍的切片形式,扩展切片的名称也流传下来,实际上不用担心,这早已是Python所支持的标准语法。

扩展切片指的是这样的切片形式:a[start:stop:step],其中step是一个非零整数,即比简单切片多了调整步长的功能,此时切片的行为可概括为:从start对应的位置出发,以step为步长索引序列,直至越过stop对应的位置,且不包括stop本身。事实上,简单切片就是step=1的扩展切片的特殊情况。需要详细解释的是step分别为正数和负数的两种情况。

step为正数

step为正数时,切片行为很容易理解,startstop截断缺省规则也与简单切片完全一致:

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[0:6:2]
 [0, 2, 4]
 >>> a[::2]
 [0, 2, 4, 6, 8]
 >>> a[:-2:2]
 [0, 2, 4, 6]
 >>> a[4::2]
 [4, 6, 8]

step为负数

step为负数时,切片将其解释为从start出发以步长|step|逆序索引序列,此时,startstop截断依然遵循前述规则,但缺省发生一点变化,因为我们说过,在缺省的情况下,Python的行为是尽可能取最大区间,此时访问是逆序的,start应尽量取大,stop应尽量取小,才能保证区间最大,因此:

按照扩充索引范围的观点,start的缺省值是无穷大(​)stop的缺省值是无穷小(​)

>>> a
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> a[5::-1]
 [5, 4, 3, 2, 1, 0]
 >>> a[:4:-2]
 [9, 7, 5]
 >>> a[::-1]
 [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

可以使用这一特性倒置序列:

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(li[::-1])
# [10,9,8,7,6,5,4,3,2,1]

混合索引

起始索引和结束索引正(+)负(-)混合索引的情况

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(li[1:-7:-1])
#  []
'''
起始索引1在结束索引-7的左边,因此从左往右取值,但步长为-1则决定了从右往左取值,两者矛盾,因此为空。
'''
print(li[-1:7:-1])
# [10, 9]
# 起始索引-1在结束索引7的右边,因此从右往左取值,而步长-1同样决定了从右往左取值,因此结果正确
```

几种特殊情况:

a=[9,2,8,7,4,5,1,5,6,8]
a[1:6:-1]    #step=-1表示从右往左取值,但是1:6表示从第二个到第七个从左往右,二者矛盾输出空列表
a[6:1]       #step缺省时为1,但是6:1表示从第七个到第二个从右往左,二者矛盾,输出为空
a[-1:-6]     #step缺省为1表示从左往右取值,但是-1:-6表示从倒数第一到倒数第六从右往左,矛盾输出为空
a[1:-6:-1]   #step=-1表示从右往左,1:-6表示从左往右,矛盾 输出为空
a[-1:6]      #step缺省为1从左到右,-1:6从右到左,两者矛盾,输出为空

多层切片

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(li[:9][3:7][-1:])
# [7]
’‘’
相当于: 
li[:9]          =[1, 2, 3, 4, 5, 6, 7, 8, 9]
li[:9][3:7]     =[4, 5, 6, 7]
li[:9][3:7][-1:]=[7]
理论上是可以无限的进行多层切片,只要上一次的切片结果不为空
‘’‘

切片用法

读取

l = [1,2,3,4,5,6,7,8]
l[:] # 取全部元素
[1, 2, 3, 4, 5, 6, 7, 8]
l[::-1] # 逆序
[8, 7, 6, 5, 4, 3, 2, 1]
l[::2] # 取下标为偶数位的元素
[1, 3, 5, 7]
l[1::2] # 下标为奇数位
[2, 4, 6, 8]
l[2:4] # 下标为 [2,4)
[3, 4]
l[:3] # 取前3位,下标为 [0,3)
[1, 2, 3]
l[:100] # 超过数组长度时,尾部截断
[1, 2, 3, 4, 5, 6, 7, 8]
l[100:0] # 起始位置大于长度时,返回空list
[]
l[-3:] # 取后3位,下标为 [n-3,n)
[6, 7, 8]
l[3:] # 下标为 [3,n)
[4, 5, 6, 7, 8]
l[:-3] # 下标为 [0, n-3)
[1, 2, 3, 4, 5]
l[3] # 取下标为3的数
4
l[-3] #l[n-3]=l[5] #取下标为n-3的数
6
l[-1] # 最后一个数,即下标为n-1的数
8
l[2::3] # 每隔3取一个数
[3, 6]
for i in range(3):
    print(l[i:i+3]) # 窗口式读取,每次读3个数,循环3次
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]

修改

l[0] = 'a' #替换l[0]
l
['a', 2, 3, 4, 5, 6, 7, 8]

插入

l[3:3] = 'c' # 在l[3]处插入元素
l
['a', 2, 3, 'c', 4, 5, 6, 7, 8]
l[:0]= 'a' # 头部插入
l
['a', 'a', 2, 3, 'c', 4, 5, 6, 7, 8]
l[len(l):0]= 'x' # 尾部插入
l
['a', 'a', 2, 3, 'c', 4, 5, 6, 7, 8, 'x']

替换

l[:4] = ['e','f'] # 替换,前4位替换为2位
l
['e', 'f', 'c', 4, 5, 6, 7, 8, 'x']
l[-3:] = ['x','y','z'] # 最后3位替换为其他3位
l
['e', 'f', 'c', 4, 5, 6, 'x', 'y', 'z']
l[::2] = [0]*5 # 奇数为置0,间隔替换时,长度需要相等 
l
[0, 'f', 0, 4, 0, 6, 0, 'y', 0]
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
li[2:6] = [6,6,6,6]
print(li)
# [1, 2, 6, 6, 6, 6, 7, 8, 9, 10]
a=[9,2,8,7,4,5,1,5,6,8]
print(f'{a=}')
#修改单个元素
a[3]='hello china'  #序列变为[9, 2, 8, 'hello china', 4, 5, 1, 5, 6, 8]
print(f'修改了第3个元素,{a=}')
#插入某个元素
a[3:3]='A'  #序列变为[9, 2, 8, 'A', 'hello china', 4, 5, 1, 5, 6, 8]
print(f'在第3个元素的地方插入了一个A,{a=}')
#替换一部分元素
a[3:5] = ['hello','world']  #序列变为[9, 2, 8, 'hello', 'world', 4, 5, 1, 5, 6, 8]
print(f'替换了第3、4元素,{a=}’)

‘’'
a=[9, 2, 8, 7, 4, 5, 1, 5, 6, 8]
修改了第3个元素,a=[9, 2, 8, 'hello china', 4, 5, 1, 5, 6, 8]
在第3个元素的地方插入了一个A,a=[9, 2, 8, 'A', 'hello china', 4, 5, 1, 5, 6, 8]
替换了第3、4元素,a=[9, 2, 8, 'hello', 'world', 4, 5, 1, 5, 6, 8]
‘''

删除

l[:2] = [] #删除前2位元素
l
[0, 4, 0, 6, 0, 'y', 0]
del l[:2] # 删除前2位元素
l
[0, 6, 0, 'y', 0]
del l[::2] # 删除奇数位元素
l
[6, 'y']

取奇偶数

li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 我们可以通过切片来进行取出li中的奇数和偶数
# 奇数
print(li[::2])
# [1, 3, 5, 7, 9]
print(li[1::2])
# [2, 4, 6, 8, 10]

你可能感兴趣的:(python,开发语言)