通用序列操作
约 1612 字大约 5 分钟
2025-04-04
序列类型是由一系列对象(包括字面值、类实例,甚至其他序列)按顺序存储的数据结构。Python 中的常见序列类型包括列表、元组、range 对象、字符串以及二进制序列
- 通用序列操作
- 索引(下标)
- 切片
- 1对同一个字符串 s = 'bob_alice_tom' 分别跑 s[4], s[-1], s[4:9], s[::-1],逐个对照位置。
- 2记住公式:切片长度 = stop - start。给定 start=2、长度=5,自己算 stop 应该填几。
- 3故意把切片终点写超出长度(如 s[2:100]),确认它不会报错,只截到末尾。
- 4用 s[::-1] 反转字符串,再用同样的写法反转列表,体会切片对所有序列通用。
序列类型是由一系列对象(包括字面值、类实例,甚至其他序列)按顺序存储的数据结构。Python 中的常见序列类型包括列表、元组、range 对象、字符串以及二进制序列
通用序列操作
参考:https://docs.python.org/zh-cn/3.13/library/stdtypes.html#common-sequence-operations
大多数序列类型(无论是可变还是不可变类型)都支持下表中列出的操作。为了方便开发者在自定义序列类型上正确实现这些操作,Python 提供了 collections.abc.Sequence 抽象基类(ABC)
此表按照优先级从低到高的顺序列出了常见的序列操作。在表格中,s 和 t 表示相同类型的序列,n、i、j 和 k 是整数,而 x 是满足 s 类型和值约束的任意对象
in 和 not in 操作符的优先级与比较操作相同。+(拼接)和 *(重复)操作符的优先级则与对应的数值运算一致(这是必要的,因为解析器无法提前判断操作数的具体类型)
| 运算 | 结果: |
|---|---|
x in s | 如果 s 中的某项等于 x 则结果为 True,否则为 False |
x not in s | 如果 s 中的某项等于 x 则结果为 False,否则为 True |
s + t | s 与 t 相拼接 |
s * n 或 n * s | 相当于 s 与自身进行 n 次拼接 |
s[i] | s 的第 i 项,起始为 0 |
s[i:j] | s 从 i 到 j 的切片 |
s[i:j:k] | s 从 i 到 j 步长为 k 的切片 |
len(s) | s 的长度 |
min(s) | s 的最小项 |
max(s) | s 的最大项 |
s.index(x[, i[, j]]) | x 在 s 中首次出现项的索引号(索引号在 i 或其后且在 j 之前) |
s.count(x) | x 在 s 中出现的总次数 |
索引(下标)
索引(也称为下标)用于标识可迭代对象中某个元素的位置。索引可以通过正整数或负整数表示:
- 正整数索引从左向右定位,起始值为 0(例如:0, 1, 2)。
- 负整数索引从右向左定位,起始值为 -1(例如:-1, -2, -3)。
例如:
python playground
name = "Sure" # 从 0 开始数
#0123 (索引值|下标值) 从左向右
#-4-3-2-1 从右向左
print(name[2]) # r
print(name[-4]) # S切片
假设我们有一个字符串 'bob_alice_tom',目标是提取其中的 'alice'。一种方法是依次通过索引获取每个字符,然后将它们拼接起来,如下所示:
python playground
name = 'bob_alice_tom'
a = name[4] # a
b = name[5] # l
c = name[6] # i
d = name[7] # c
e = name[8] # e
print(a + b + c + d + e) # 拼接并打印字符串同样,我们也可以使用循环逐一提取字符并拼接:
python playground
name = 'bob_alice_tom'
i = 4
s = ''
while i <= 8:
s += name[i]
i += 1
print(s)然而,这种方法过于繁琐,尤其是在处理较长的字符串时。为此,Python 提供了一种简便的方式——切片。切片的基本语法和用法如下:
python playground
name = 'bob_alice_tom'
# 0123456789
print(name[4:9]) # [起始位置:终止位置] 顾头不顾腚(起始位置保留,终止位置不保留)-> alice
print(name[-3:]) # [起始位置:终止位置(默认到结尾)] 顾头不顾腚 -> tom
print(name[:]) # [起始位置(默认从开头):终止位置(默认到结尾)] 顾头不顾腚 -> bob_alice_tom切片的一个实用技巧是:终止位置 = 起始位置 + 切片长度。例如,在上述例子中,起始位置为 4,切片长度为 5,因此终止位置为 4 + 5 = 9
有时,我们可能需要每隔一个字符提取一次。例如,对于字符串 'bob_alice_tom',我们希望提取第 3、5、7 位的字符 'b'、'a'、'i'。可以继续使用原始方法分别取值并拼接:
python playground
name = 'bob_alice_tom'
a = name[2]
b = name[4]
c = name[6]
print(a + b + c)虽然这种方法可行,但效率较低。更优雅的解决方案是引入切片的第三个参数——步长。步长的默认值为 1,但我们可以通过调整它来控制提取的间隔。例如:
python playground
name = 'bob_alice_tom'
#0123456789
#-6-5-4-3-2-1
print(name[2:7:2]) # [起始位置:终止位置:步长(默认为1)] -> bai如果将步长设置为负值(如 -1),可以实现从右向左的反向提取:
python playground
name = 'bob_alice_tom'
print(name[-1:3:-1]) # 步长可以控制查找方向 -> mot_ecila需要注意的是,索引操作要求参数不能超出最大索引值,否则会引发错误。但在切片操作中,即使终止位置超出范围,程序也不会报错,而是自动截取到字符串末尾:
python playground
name = 'bob_alice_tom'
print(name[2:20:2]) # baietm最后提醒一点:索引和切片仅适用于有序数据结构(如字符串、列表、元组)。对于无序数据类型(如整型、布尔值、字典、集合等),则无法进行索引或切片操作
- 切片语法 s[start:stop:step] 是所有序列通用的,遵循“顾头不顾腚”,stop 不被包含。
- 索引越界会 IndexError,但切片越界会自动截断,不会报错 —— 这是切片最大的安全特性。
- step 为负时从右向左取,start/stop 也要相应地从右往左指,否则得空序列。
- 切片返回的是同类型的新对象(字符串切出字符串,列表切出列表),原数据不会被改动。
版权所有
版权归属:Shuo Liu
