--- sources: [summaries/01_Iteration_protocol.md, summaries/04_Sequences.md] brief: Python 切片是一种用半开区间从序列中提取、替换或删除子序列的语法。 --- # Python 切片 Python 切片是一种从Python序列中选取子序列的语法,常用于字符串、列表、元组等有序数据结构。它在 [[summaries/04_Sequences]] 中作为序列操作的核心内容之一出现。 ## 基本语法 切片的基本形式是: ```python s[start:end] ``` 其中: - `s` 是一个序列,例如字符串、列表或元组。 - `start` 是切片起始索引。 - `end` 是切片结束索引。 - 结果包含 `start` 对应的元素,但不包含 `end` 对应的元素。 例如: ```python a = [0, 1, 2, 3, 4, 5, 6, 7, 8] a[2:5] # [2, 3, 4] ``` 这里 `a[2:5]` 取出索引 `2`、`3`、`4` 的元素,但不包括索引 `5` 的元素。 ## 半开区间规则 Python 切片遵循半开区间规则: ```text [start, end) ``` 也就是说: - 包含起点 `start`。 - 不包含终点 `end`。 这与 `range()` 的行为一致: ```python range(2, 5) # 2, 3, 4 ``` 这种设计使得切片长度容易计算: ```python len(s[start:end]) == end - start ``` 前提是索引在正常范围内。 相关概念可参见 range函数。 ## 省略 start 或 end 切片中的 `start` 和 `end` 都可以省略。 ### 省略 start 如果省略 `start`,默认从序列开头开始: ```python a[:3] # [0, 1, 2] ``` 等价于: ```python a[0:3] ``` ### 省略 end 如果省略 `end`,默认一直取到序列结尾: ```python a[-5:] # [4, 5, 6, 7, 8] ``` ### 同时省略 start 和 end 如果两者都省略,则得到整个序列的浅拷贝: ```python a[:] # [0, 1, 2, 3, 4, 5, 6, 7, 8] ``` 对于列表来说,这常用于复制列表。 ## 负索引与切片 Python 序列支持负索引: - `-1` 表示最后一个元素。 - `-2` 表示倒数第二个元素。 - 依此类推。 负索引也可以用于切片: ```python a = [0, 1, 2, 3, 4, 5, 6, 7, 8] a[-5:] # [4, 5, 6, 7, 8] ``` 这表示从倒数第 5 个元素开始,一直取到结尾。 ## 切片适用于多种序列 切片是序列类型的通用操作,常见适用对象包括: - 字符串: ```python s = 'Hello' s[1:4] # 'ell' ``` - 列表: ```python a = [0, 1, 2, 3] a[1:3] # [1, 2] ``` - 元组: ```python t = ('GOOG', 100, 490.1) t[:2] # ('GOOG', 100) ``` 切片返回的结果通常与原序列类型一致: - 字符串切片返回字符串。 - 列表切片返回列表。 - 元组切片返回元组。 ## 列表的切片赋值 在可变序列列表中,切片不仅可以读取,还可以重新赋值。 ```python a = [0, 1, 2, 3, 4, 5, 6, 7, 8] a[2:4] = [10, 11, 12] ``` 结果是: ```python [0, 1, 10, 11, 12, 4, 5, 6, 7, 8] ``` 这里原来的 `a[2:4]` 是: ```python [2, 3] ``` 它被替换为: ```python [10, 11, 12] ``` 注意:替换片段不需要与原片段长度相同。因此,切片赋值可以改变列表长度。 这体现了列表作为可变序列的特性。相比之下,字符串和元组不可变,不能通过切片赋值修改。 相关概念:Python序列。 ## 切片删除 列表中的切片也可以被删除: ```python a = [0, 1, 2, 3, 4, 5, 6, 7, 8] del a[2:4] ``` 结果是: ```python [0, 1, 4, 5, 6, 7, 8] ``` 这里删除了索引 `2` 和 `3` 的元素,也就是原来的 `2` 和 `3`。 ## 与 range() 的一致性 切片和 `range()` 都采用“不包含结束值”的规则。 例如: ```python a[2:5] # 索引 2, 3, 4 range(2, 5) # 数字 2, 3, 4 ``` 这种一致性降低了理解成本,也让序列处理、循环计数和索引计算更加统一。 参见 range函数 与 [[summaries/04_Sequences]]。 ## 常见使用场景 ### 提取前几个元素 ```python a[:3] ``` ### 提取后几个元素 ```python a[-5:] ``` ### 去掉开头或结尾部分 ```python a[1:] # 去掉第一个元素 a[:-1] # 去掉最后一个元素 ``` ### 复制列表 ```python b = a[:] ``` ### 替换列表中间一段 ```python a[2:4] = [10, 11, 12] ``` ### 删除列表中间一段 ```python del a[2:4] ``` ## 易错点 ### 1. end 不包含在结果中 很多初学者会误以为 `s[2:5]` 包含索引 `5`。实际上它只包含 `2`、`3`、`4`。 ### 2. 切片索引必须是整数 `start` 和 `end` 必须是整数索引,不能使用浮点数或其他不合适的类型。 ### 3. 只有可变序列支持切片赋值 列表支持: ```python a[1:3] = [7, 8] ``` 但字符串和元组不支持类似操作,因为它们是不可变对象。 ### 4. 切片赋值可以改变列表长度 如下代码是合法的: ```python a[2:4] = [10, 11, 12, 13] ``` 替换后的元素数量可以多于或少于原片段。 ## 与其他概念的关系 - Python序列:切片是序列类型的基本操作之一。 - range函数:切片和 `range()` 都采用半开区间规则。 - Python解包:切片常用于先取得子序列,再进一步解包或处理。 - enumerate函数:当需要带索引遍历序列时,`enumerate()` 通常比手动切片或索引循环更清晰。 - [[summaries/04_Sequences]]:本文档系统介绍了序列、切片、循环、`enumerate()` 和 `zip()` 等基础工具。 ## 核心总结 Python 切片提供了一种简洁、统一的方式来处理序列的一部分。它基于半开区间 `[start, end)`,支持省略边界、负索引,并在列表中进一步支持切片赋值和删除。掌握切片是理解 Python 序列处理风格的重要基础。 See also: [[summaries/01_Iteration_protocol]]