295 lines
5.5 KiB
Markdown
295 lines
5.5 KiB
Markdown
---
|
|
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]] |