如何使用 Python 进行切片

Posted on Wed, 25 Dec 2024 16:09:24 +0800 by LiangMingJian


什么是切片

在 Python 中,切片是一种通过指定索引范围来获取一个序列中部分元素的操作,序列一般指字符串、列表、元组等。通过切片操作,用户可以快速的从序列中获取值,而不需要遍历序列,提高了程序性能。

切片的语法

切片的基本语法为:

new_sequence = sequence[start:stop:step]
  • sequence:目标序列
  • start:开始索引,默认为 0,包含
  • stop:结束索引,默认为目标序列长度,不包含
  • step:步长,可选参数,默认为 1

上述开始索引和结束索引的包含和不包含是指在切片操作中,返回的结果是【开始索引】到【结束索引前一个】的数据。比如下面示例:

seq = [0, 1, 2, 3, 4, 5]

print(seq[1:4]) 

其输出结果是 [1, 2, 3],索引范围是 1 到 3。

另外,切片操作会生成一个新的序列对象,对原序列的所有切片都不会影响到原序列。比如下面示例:

seq = [0, 1, 2, 3, 4, 5]
new_seq = seq[1:4]

print(seq)
print(new_seq)

其输出结果中 seq 还是原本的样子。

切片的顺序

在 Python 中,切片的顺序由 start(开始索引)、stop(结束索引)和 step(步长)共同决定。

主要分为以下 3 种情况:

正序

当 step(步长)为正数时,切片从左往右执行。此时 start(开始索引)必须小于 stop(结束索引),否则切片结果会返回空。特别的,当步长为 1 时,可以省略。

比如下方示例:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 步长为 1,可以省略输入
>>> seq[1:6]
>>> [1, 2, 3, 4, 5]

# 步长为 2
>>> seq[1:6:2]
>>> [1, 3, 5]

# 开始索引大于结束索引
>>> seq[6:1]
>>> []

# 开始索引等于结束索引
>>> seq[6:6]
>>> []

逆序

当 step(步长)为负数时,切片从右往左执行。此时 start(开始索引)必须大于 stop(结束索引),否则切片结果会返回空。

比如下方示例:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 步长为 -1
>>> seq[6:1:-1]
>>> [6, 5, 4, 3, 2]

# 步长为 -2
>>> seq[6:1:-2]
>>> [6, 4, 2]

# 开始索引小于结束索引
>>> seq[1:6:-1]
>>> []

# 开始索引等于结束索引
>>> seq[6:6:-1]
>>> []

边界

特别的,开始索引或结束索引可以在切片操作时忽略,此时切片的开始和结束位置将由切片的顺序决定。

主要分为以下三种情况:

开始索引或结束索引都忽略

  • 如果步长是正,则顺序从左到右,则以序列头作为开始,序列尾作为结束。
  • 如果步长是负,则顺序从右到左,则以序列尾作为开始,序列头作为结束。
# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 开始索引和结束索引都忽略,步长为 1
>>> seq[::1]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 因为步长为 1 时可以忽略,所以上面等效于
>>> seq[:]
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 开始索引和结束索引都忽略,步长为 -1
>>> seq[::-1]
>>> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

只忽略开始索引:

  • 如果步长是正,则顺序从左到右,则以序列头作为开始,传入的结束索引作为结束。
  • 如果步长是负,则顺序从右到左,则以序列尾作为开始,传入的结束索引作为结束。
# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 只忽略开始索引,步长为 1
>>> seq[:6:1]
>>> [0, 1, 2, 3, 4, 5]

# 只忽略开始索引,步长为 -1
>>> seq[:6:-1]
>>> [9, 8, 7]

只忽略结束索引:

  • 如果步长是正,则顺序从左到右,则以传入的开始索引作为开始,序列尾作为结束。
  • 如果步长是负,则顺序从右到左,则以传入的开始索引作为开始,序列头作为结束。
# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 只忽略结束索引,步长为 1
>>> seq[1::1]
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 只忽略结束索引,步长为 -1
>>> seq[1::-1]
>>> [1, 0]

索引的方式

切片的索引包括正索引和负索引两部分,如下图所示:

对于一个长度 10 的列表,其正索引由 0 到 9,其负索引由 -1 到 -10。

负索引的使用

负索引的使用与正索引基本一致,其同样遵循切片顺序的 3 种情况。

正序(步长为正数)

此时,切片同样从左往右执行,同样要求 start(开始索引)必须小于 stop(结束索引),同样可以省略步长 1 的输入。不同的是,数据的获取是从序列尾开始的。

比如下方示例:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 步长为 1,可以省略输入
# 切片范围由倒数第 6 个,到倒数第 1 个前 1 个
>>> seq[-6:-1]
>>> [4, 5, 6, 7, 8]

# 步长为 2
>>> seq[-6:-1:2]
>>> [4, 6, 8]

# 开始索引大于结束索引
>>> seq[-1:-6]
>>> []

# 开始索引等于结束索引
>>> seq[-6:-6]
>>> []

逆序(步长为负数)

此时,切片同样从右往左执行,同样要求 start(开始索引)必须大于 stop(结束索引)。不同的是,数据的获取是从序列尾开始的。

比如下方示例:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 步长为 -1
# 切片范围由倒数第 1 个,到倒数第 6 个后 1 个
>>> seq[-1:-6:-1]
>>> [9, 8, 7, 6, 5]

# 步长为 -2
>>> seq[-1:-6:-2]
>>> [9, 7, 5]

# 开始索引小于结束索引
>>> seq[-6:-1:-1]
>>> []

# 开始索引等于结束索引
>>> seq[-6:-6:-1]
>>> []

特殊边界

只忽略开始索引:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 只忽略开始索引,步长为 1
# 以序列头作为开始,以倒数第 6 个数据作为切片结尾
>>> seq[:-6:1]
>>> [0, 1, 2, 3]

# 只忽略开始索引,步长为 -1
# 以序列尾作为开始,以倒数第 6 个数据作为切片结尾
>>> seq[:-6:-1]
>>> [9, 8, 7, 6, 5]

只忽略结束索引:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 只忽略结束索引,步长为 1
# 以倒数第 2 个作为开始,以序列尾作为切片结尾
>>> seq[-2::1]
>>> [8, 9]

# 只忽略结束索引,步长为 -1
# 以倒数第 2 个作为开始,以序列头作为切片结尾
>>> seq[-2::-1]
>>> [8, 7, 6, 5, 4, 3, 2, 1, 0]

正负索引混用

当正负索引混用时,上述正序和逆序切片的开始索引和结束索引大小限制会有极大出入,不能直接的将正索引和负索引进行大小比较。

此时对于负索引,应当与序列长度相加,相加后才与正索引进行比较。

比如下述示例:

# python 控制台
>>> seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 切片顺序由左到右,正序,要求开始索引必须小于结束索引
# 将负索引与序列长度 10 相加得 4
# 此时开始索引 1 小于 4,显然成立,切片范围第 1 个到第 4 个前 1 个
>>> seq[1:-6]
>>> [1, 2, 3]

# 切片顺序由右到左,逆序,要求开始索引必须大于结束索引
# 将负索引与序列长度 10 相加得 4
# 此时开始索引 1 小于 4,显然不成立,输出为空
>>> seq[1:-6:-1]
>>> []

特殊用法

通过切片给原序列插入元素

seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
seq[2:2] = [100, 300]  # 在索引 2 的地方插入数据

print(seq)
"""
[0, 1, 100, 300, 2, 3, 4, 5, 6, 7, 8, 9]
"""

通过切片给原序列替换元素

seq = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
seq[0:2] = [100, 300]  # 在索引 0 的地方按顺序替换数据

print(seq)
"""
[100, 300, 2, 3, 4, 5, 6, 7, 8, 9]
"""