知识点

Python切片

定义

切片用sequence[start:stop:step] 从序列中取出一个子序列,区间左闭右开,取的是下标满足 start≤i<stopstart \le i < stop 的元素。

  • start:起始下标,包含在结果里。
  • stop:结束下标,不包含在结果里。
  • step:步长,默认1;为负时从右向左取。

索引从0开始。长度为 nn 的序列,正索引是0到n-1,负索引是 -1(最后一个)到 -n(第一个),-k等价于n-k。省略的参数由step的符号决定默认值:

参数step > 0step < 0
start0len-1,即最后一个元素
stoplen,越过末尾-len-1,越过开头

切片的行为

步长决定方向和间隔

  • step为正:从start向右取,停在stop之前,每隔step个位置取一个;
  • step为负:从start向左取,停在stop之后;
  • step不能为0,否则抛出ValueError。

越界只影响结果,不报错

切片会把越界的端点截到序列边界内,因此结果可能是原序列的一部分,也可能是空序列,但不会抛异常。直接写单个下标a[100] 或a[-100] 才是索引访问,越界会抛IndexError。

切片返回新序列

切片得到的是新的序列对象,不是原序列的别名。对列表切片后修改切片,不会改动原列表;但切片只复制最外层,切片里的元素仍与原列表指向同一批对象。

切片是否返回新容器与其中的元素是否被复制是两个层次。容器可变性和别名行为另见Python对象可变性。

例子

用切片取子序列

slicing.py
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a[2:5] # [2, 3, 4]
a[:3] # [0, 1, 2],前3个
a[-3:] # [7, 8, 9],后3个
a[::2] # [0, 2, 4, 6, 8],偶数位置
a[::-1] # [9, 8, ..., 0],逆序
a[5:2:-1] # [5, 4, 3],从5向左取到3,不含a[2]

a[5:2:-1] 的stop是2,但负步长同样不包含终点,所以取到a[3] 为止。

切片越界与索引越界

bounds.py
a = [0, 1, 2]
print(a[1:10]) # [1, 2]
print(a[10:]) # []
print(a[10]) # IndexError

修改切片不影响原列表

slice-copy.py
a = [1, 2, 3]
b = a[:]
b[0] = 100
print(a) # [1, 2, 3]
print(b) # [100, 2, 3]
题集

练习

  1. a = [0, 1, 2, 3, 4, 5],a[1:5:2] 的结果是:

    选择答案
    参考解答

    从下标1开始,到下标5之前,每隔2个取一个,取到a[1] 和a[3]。

  2. 长度为10的列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],a[-3:] 的结果是:

    选择答案
    参考解答

    -3对应下标7,从7取到末尾,得到最后3个元素。

  3. a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],a[::-1][0] 的值是 。

    参考解答

    a[::-1] 是逆序列表 [9, 8, ..., 0],再取下标0得到9。

交互探索

切片究竟选中了哪些元素?

调整切片起点、终点和步长,观察选中的位置与返回顺序。

正在准备演示…