切片(slicing)是 Python 处理序列数据的核心技能 。
它不仅适用于列表、字符串,还能用于多维数组(如 NumPy 矩阵)。
本文通过大量
🔹 1. 基本语法(一维)
sequence[start:stop:step]
start:起始索引(包含),默认0stop:结束索引(不包含),默认为序列长度step:步长,默认1;负数表示反向
💡 切片返回新对象,不修改原序列(除非显式赋值)。
🔹 2. 一维切片示例(列表、字符串)
lst = [0, 1, 2, 3, 4, 5]
# 基础切片
print("lst[1:4] =", lst[1:4]) # [1, 2, 3]
# 省略边界
print("lst[:3] =", lst[:3]) # [0, 1, 2]
print("lst[3:] =", lst[3:]) # [3, 4, 5]
print("lst[:] =", lst[:]) # [0, 1, 2, 3, 4, 5] → 浅拷贝
# 负索引
print("lst[-3:] =", lst[-3:]) # [3, 4, 5]
print("lst[:-2] =", lst[:-2]) # [0, 1, 2, 3]
# 步长
print("lst[::2] =", lst[::2]) # [0, 2, 4]
print("lst[::-1] =", lst[::-1]) # [5, 4, 3, 2, 1, 0] → 反转
# 越界安全
print("lst[10:20] =", lst[10:20]) # [](不会报错)
#多层切片
x = "0123456789"
# 分解:
a = x[2:] # "23456789"
b = a[:6] # "234567"
c = b[::2] # "246"
# 链式写法:
result = x[2:][:6][::2]
print("x[2:][:6][::2] =", result) # "246"
🔹 3. 字符串与元组切片(不可变序列)
s = "Python"
tup = (10, 20, 30, 40)
print("s[1:4] =", s[1:4]) # "yth"
print("s[::-1] =", s[::-1]) # "nohtyP"
print("tup[1:] =", tup[1:]) # (20, 30, 40)
print("tup[::2] =", tup[::2]) # (10, 30)
⚠️ 字符串和元组不可变,切片只能读取,不能赋值修改。
🔹 4. 用切片修改列表(仅限可变序列)
lst = [0, 1, 2, 3, 4]
# 替换子序列
lst[1:3] = ['a', 'b']
print("替换后:", lst) # [0, 'a', 'b', 3, 4]
# 删除元素
lst[1:3] = []
print("删除后:", lst) # [0, 3, 4]
# 插入元素(在索引 1 处插入)
lst[1:1] = [99, 88]
print("插入后:", lst) # [0, 99, 88, 3, 4]
# 清空列表
lst[:] = []
print("清空后:", lst) # []
🔹 5. 多维切片(以 NumPy 为例)
虽然 Python 原生列表支持嵌套切片(如
lst[1][2:4]),但真正的多维切片需借助 NumPy 。NumPy 的切片语法更强大、高效,且支持广播。
✅ 安装 NumPy(如未安装)
pip install numpy
示例:二维数组切片
import numpy as np
# 创建 4x5 矩阵
arr = np.arange(20).reshape(4, 5)
print("原始矩阵:\n", arr)
# 输出:
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
# 语法:arr[行切片, 列切片]
# 取第 1~2 行(不含第 3 行),第 2~4 列(不含第 4 列)
print("\narr[1:3, 2:4] =\n", arr[1:3, 2:4])
# [[7 8]
# [12 13]]
# 取所有行,每隔一列取一列
print("\narr[:, ::2] =\n", arr[:, ::2])
# [[ 0 2 4]
# [ 5 7 9]
# [10 12 14]
# [15 17 19]]
# 反转所有行和列
print("\narr[::-1, ::-1] =\n", arr[::-1, ::-1])
# [[19 18 17 16 15]
# [14 13 12 11 10]
# [ 9 8 7 6 5]
# [ 4 3 2 1 0]]
# 取最后一行
print("\n最后一行 arr[-1, :] =", arr[-1, :]) # [15 16 17 18 19]
print("等价写法 arr[-1] =", arr[-1]) # 同上(NumPy 允许省略后续冒号)
# 取第一列
print("\n第一列 arr[:, 0] =", arr[:, 0]) # [ 0 5 10 15]
# 使用步长:隔行隔列取
print("\n隔行隔列 arr[::2, ::2] =\n", arr[::2, ::2])
# [[ 0 2 4]
# [10 12 14]]
🔹 6. 三维及更高维切片
# 创建 2x3x4 的三维数组
arr3d = np.arange(24).reshape(2, 3, 4)
print("三维数组 shape:", arr3d.shape) # (2, 3, 4)
# 语法:arr[深度, 行, 列]
print("\n取第一个"页"的全部:\n", arr3d[0, :, :])
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 取每个"页"的中间行、前两列
print("\narr3d[:, 1, :2] =\n", arr3d[:, 1, :2])
# [[ 4 5]
# [16 17]]
# 反转深度方向
print("\n反转"页"顺序:\n", arr3d[::-1, :, :])
# 先输出第 1 页(原索引 1),再输出第 0 页
🔹 7. 注意事项 & 常见陷阱
❌ 误区:Python 原生列表不支持 arr[:, 1] 这种写法
nested_lst = [[1, 2], [3, 4], [5, 6]]
# nested_lst[:, 1] → 语法错误!
# 必须用循环或 NumPy
✅ 正确做法:多维切片请用 NumPy
⚠️ 负步长的边界行为
lst = [0, 1, 2, 3, 4]
print(lst[4::-1]) # [4, 3, 2, 1, 0] → 包含索引 0
print(lst[:0:-1]) # [4, 3, 2, 1] → 不包含索引 0
✅ 安全建议:不确定时,先打印 .shape 或 len()
✅ 总结:切片核心规则
| 场景 | 语法 |
|---|---|
| 一维复制 | seq[:] |
| 一维反转 | seq[::-1] |
| 二维取子矩阵 | arr[row_start:row_stop, col_start:col_stop] |
| 多维通用 | arr[dim0_slice, dim1_slice, ..., dimN_slice] |
| 隔行/列取 | arr[::2, ::2] |
| 反向遍历 | arr[::-1, ::-1] |