type
status
date
slug
summary
tags
category
icon
password
📝 通用序列操作
大多数序列类型,包括可变类型和不可变类型都支持下表中的操作。collections.abc.Sequence ABC被提供用来更容易地在自定义序列类型上正确地实现这些操作。
此表按优先级升序列出了序列操作。在表格中,s 和 t 是具有相同类型的序列,n, i, j 和 k 是整数而 x 是任何满足 s 所规定的类型和值限制的任意对象。
in 和 not in 操作具有与比较操作相同的优先级。+ (拼接) 和 * (重复) 操作具有与对应数值运算相同的优先级。
运算 | 结果 | 备注 |
x in s | 若 s 中某一项等于 x 则为 True,否则为 False | (1) |
x not in s | 若 s 中某一项等于 x 则为 False,否则为 True | (1) |
s + t | 将序列 s 与 t 拼接得到新序列 | (6)(7) |
s * n 或 n * s | 将序列 s 重复 n 次后拼接成新序列 | (2)(7) |
s\[i] | 返回序列 s 的第 i 项,下标从 0 开始 | (3) |
s\[i:j] | 返回序列 s 从索引 i 到 j(不含 j)的切片 | (3)(4) |
s\[i:j:k] | 返回序列 s 从索引 i 到 j、步长为 k 的切片 | (3)(5) |
len(s) | 返回序列 s 的元素个数 | — |
min(s) | 返回序列 s 中的最小项 | — |
max(s) | 返回序列 s 中的最大项 | — |
s.index(x\[, i[, j]]) | 返回 x 在 s 中首次出现的位置索引;可限定搜索范围 [i, j) | (8) |
s.count(x) | 返回 x 在序列 s 中出现的总次数 | — |
1、index(self, value, start=0, stop=sys.maxsize)
→ int
1.1、在序列的指定切片 [start:stop) 范围内,从左到右查找第一次出现的元素 value,并返回其下标。若未找到,抛出 ValueError。
1.2、参数
- value(必选):要查找的元素,与序列元素做 == 比较。
- start(可选,默认为 0):切片起始下标(包含)。
- stop(可选,默认为 sys.maxsize):切片结束下标(不包含)。
1.3、返回值
- 找到时返回 int 类型的下标(相对于原序列,而非切片)。
- 未找到时抛出 ValueError: <value> is not in sequence。
1.4、边界/细节
- 支持负索引;start 或 stop 越界会被自动截断。
- 若序列中允许重复元素,只返回 最左侧 的第一次出现。
- 时间复杂度平均为 O(n),因为需要线性扫描。
2、count(self, value)
→ int
2.1、统计序列中 所有位置(无切片参数)与 value 相等的元素出现次数。
2.2、参数
- value(必选):要计数的元素,使用 == 比较。
2.3、返回值
- int:出现次数;若一次也没有返回 0。
- 不会抛出异常,即使元素不存在。
2.4、边界/细节
- 同样使用线性扫描,时间复杂度 O(n)。
- 对于可变序列(如 list),统计的是调用时刻的快照。
- 字符串、元组、列表、bytes 等内部实现均遵循同一语义。
3、len()
获取列表长度
4、max()
获取列表值最大的元素
5、min()
获取列表值最小的元素
📝 不可变序列类型
不可变序列类型普遍实现而可变序列类型未实现的唯一操作就是对hash() 内置函数的支持。
这种支持允许不可变类型,例如tuple 实例被用作dict 键,以及存储在set 和frozenset 实例中。
尝试对包含有不可哈希值的不可变序列进行哈希运算将会导致TypeError。
📝 可变序列类型
以下表格中的操作是在可变序列类型上定义的。collections.abc.MutableSequence ABC 被提供用来更容易地在自定义序列类型上正确实现这些操作。
表格中的 s 是可变序列类型的实例,t 是任意可迭代对象,而 x 是符合对 s 所规定类型与值限制的任何对象 (例如,bytearray 仅接受满足 0 <= x <= 255 值限制的整数)。
运算 | 结果 | 备注 |
s\[i] = x | 将 s 的第 i 项替换为 x | — |
s\[i:j] = t | 将 s 从 i 到 j 的切片替换为可迭代对象 t 的内容 | — |
del s\[i:j] | 等同于 s\[i:j] = \[] | — |
s\[i:j:k] = t | 将 s\[i:j:k] 的元素替换为 t 的元素 | (1) |
del s\[i:j:k] | 从列表中移除 s\[i:j:k] 的元素 | — |
s.append(x) | 将 x 添加到序列的末尾 | 等同于 s\[len(s):len(s)] = \[x] |
s.clear() | 从 s 中移除所有项 | 等同于 del s\[:] (5) |
s.copy() | 创建 s 的浅拷贝 | 等同于 s\[:] (5) |
s.extend(t) 或 s += t | 用 t 的内容扩展 s | 等同于 s\[len(s):len(s)] = t |
s *= n | 使用 s 的内容重复 n 次来对其进行更新 | (6) |
s.insert(i, x) | 在索引 i 处插入 x | 等同于 s\[i:i] = \[x] |
s.pop() 或 s.pop(i) | 移除并返回索引 i 处的元素 | (2) |
s.remove(x) | 移除第一个等于 x 的元素 | (3) |
s.reverse() | 就地逆序列表元素 | (4) |
1、append(self, value)
→ None
- 作用:在序列尾部追加单个元素。
- 参数:value – 待追加的对象。
- 返回值:None(就地修改)。
- 复杂度:均摊 O(1)。
2、clear(self)
→ None
- 作用:删除序列中所有元素,使其长度变为 0。
- 参数:无。
- 返回值:None。
3、copy(self)
→ MutableSequence
- 作用:返回序列的浅拷贝(新对象,元素本身不复制)。
- 参数:无。
- 返回值:与原序列同类型的空壳副本。
4、extend(self, iterable)
→ None
- 作用:将可迭代对象中的所有元素依次追加到尾部。
- 参数:iterable – 任意可迭代对象(列表、元组、生成器等)。
- 返回值:None。
- 复杂度:O(k),k 为 iterable 长度。
5、insert(self, index, value)
→ None
- 作用:在指定下标前插入元素;负索引也可。
- 参数:index – 插入位置;value – 待插入元素。
- 返回值:None。
- 复杂度:O(n)。
6、pop(self, index=-1)
→ element
- 作用:移除并返回指定下标的元素;默认移除最后一个。
- 参数:index – 可选,默认为 -1。
- 返回值:被弹出的元素。
- 异常:IndexError(空序列或越界)。
7、remove(self, value)
→ None
- 作用:删除第一个与 value 相等的元素。
- 参数:value – 待移除的值(按 == 比较)。
- 返回值:None。
- 异常:ValueError(元素不存在)。
8、reverse(self)
→ None
- 作用:就地反转序列顺序。
- 参数:无。
- 返回值:None。
- 复杂度:O(n)。
📝 列表 list
列表是可变序列,通常用于存放同类项目的集合(其中精确的相似程度将根据应用而变化)
1、构造方法:
1.1、字面量构造(空列表或初值列表)
最轻量,O(1) 创建;
只负责“容器”,不提供线程安全或性能优化。
1.2、构造函数 list(iterable)
任何可迭代对象 → 列表;
复杂度 O(n),n 为去重后元素个数。
1.3、列表推导式 / 生成器表达式
语法灵活,可直接生成“队列初始数据”。
1.4、从其他容器转换
源容器 | 示例 | 备注 |
tuple | list((1,2,3)) | 元组 → 列表 |
set | list({1,2,3}) | 集合 → 列表(无序) |
dict | list({'a':1,'b':2}) | 键视图 → 列表 |
文件对象 | list(open('file.txt')) | 每行一个元素 |
1.5、 展开构造
Python 3.5+ 的解包语法,用于“一次性拼接”。
1.6、双端队列(deque)—— 官方推荐高性能队列
生产环境 推荐 collections.deque,因为它在两端插入/删除都是 O(1),而 list.insert(0, x) 是 O(n)。
完全兼容 list 的迭代、切片读取;
额外方法:appendleft, popleft, extendleft, rotate, maxlen。
1.7、线程安全队列(queue 模块)
若需要在 多线程 中当真正队列,使用
queue.Queue
/LifoQueue
/PriorityQueue
,内部用锁保护与 list 接口不同:通过 put, get, task_done 管理。
1.8、性能对比速览
操作 | list | deque | Queue |
尾部 append | O(1) | O(1) | O(1) |
头部 insert | O(n) | O(1) | O(1) |
线程安全 | ❌ | ❌ | ✅ |
可切片 | ✅ | ✅ | ❌ |
临时/单线程:
q = \[]
或 q = list(iterable)
。高频两端操作:用
collections.deque(iterable)
。多线程安全:用
queue.Queue(maxsize)
。2、list.sort(*, key=None, reverse=False)
2.1、作用
- 原地重排:调用后原列表顺序被永久改变。
- 稳定排序:排序前后,相等元素的相对顺序不变。
- 多字段排序:可一次指定多个键,实现多级排序(例如先按年龄再按姓名)。
2.2、参数
形参 | 类型 | 默认值 | 说明 |
key | callable 或 None | None | 排序键函数。对每个元素调用 key(element) ,返回值作为排序依据。常见用法:<br>- key=str.lower (忽略大小写)<br>- key=lambda x: x.age (按对象属性)<br>- key=operator.itemgetter(1) (按元组第二字段) |
reverse | bool | False | 为 True 时降序排序;False 为升序。 |
2.3、返回值
始终返回 None。
因为排序是原地操作,所以 不返回新列表;若写 new_list = old_list.sort(),会得到 None,这是常见错误。
3、公共功能
3.1、运算符 +
相加,两个列表相加获取生成一个新的列表。
3.2、运算符 *
相乘,列表*整型 将列表中的元素再创建N份并生成一个新的列表。
3.3、索引(下标)取值
超出索引范围会报错。
由于字符串是不可变类型,所以他只有索引读的功能,而列表可以进行 读、改、删
3.4、切片取值
- 和字符串一样,列表也可以切片
- 使用语法:列表\[start : end : step],获取列表中在 [start, end) 范围的子列表
- 注意范围 [start, end) 包含 start,不包含 end
- step 是步长,设为 n,则每隔 n 个元素获取一次
3.5、切片赋值
赋值的值也必须是列表,否则会报错 TypeError: can only assign an iterable
3.6、关键字 in
通过关键字 in 检查列表中是否包含指定元素,返回 bool 值
not in 则是取反
4、易错点
在 Python 里,一边遍历列表一边删元素是新手最容易踩的坑之一,核心问题是:列表是可变序列,删除操作会立即改变其长度和索引,从而让循环“错位”。下面用 3 个典型场景说明坑点、原因及正确做法。
4.1、漏删 / 跳过元素
原因:第一次删下标 1 的
2
后,后面的元素整体前移,原下标 2 的 2
变成了下标 1,但 for 循环的指针已经走到下标 2 了,于是被跳过。4.2、IndexError:索引越界
原因:列表长度在循环中不断缩短,而
range(len(lst))
一开始就把长度固定为 3,当 i=2
时列表只剩 1 个元素,导致越界。4.3、隐藏的副作用(列表推导式同理)
原因:
list.remove
会就地修改原列表,列表推导式内部迭代器仍在同一列表上工作,行为完全不可预测。4.4、✅ 正确姿势
方法 | 代码示例 | 说明 |
倒序遍历 | for i in range(len(lst)-1, -1, -1): if cond: del lst[i] | 删除不影响未遍历索引 |
列表拷贝 | for x in lst[:]: if cond: lst.remove(x) | 遍历副本,修改原列表 |
生成新列表 | lst = [x for x in lst if not cond] | 函数式写法,最简洁 |
filter | lst = list(filter(lambda x: not cond, lst)) | 与推导式等价 |
4.5、一句话总结
不要在同一个可变列表上同时进行“遍历指针”和“长度修改”两类操作;要么倒序、要么遍历副本、要么生成新列表。
📝 元组tuple
元组是不可变序列,通常用于储存异构数据的多项集(例如由enumerate() 内置函数所产生的二元组)。
元组也被用于需要同构数据的不可变序列的情况(例如允许存储到set 或dict 的实例)。
1、构造方法:
1.1、字面量括号法(最常用)
细节 | 说明 |
逗号是标识符 | 没有逗号, (42) 只是表达式分组,类型为 int 。 |
性能 | CPython 在编译期直接生成 BUILD_TUPLE ,O(1)。 |
1.2、内置构造函数 tuple(iterable=())
形参 | 默认值 | 复杂度 |
iterable | () | O(n),n 为元素个数 |
1.3、生成器 / 推导式转元组
生成器表达式惰性迭代,节省一次中间列表内存。
1.4、序列拆包与星号展开
Python 3.5+ 支持 解包语法,编译器生成
BUILD_TUPLE_UNPACK
。1.5、嵌套元组(tuple 嵌套 tuple)
完全合法,用于 坐标点、树节点、多维索引 等场景。
1.6、命名元组(namedtuple)—— 语义元组
仍是
tuple
子类,但带字段名,提升可读性。1.7、单元素陷阱与布尔陷阱
表达式 | 结果类型 | 说明 |
(42) | int | 无逗号,只是括号分组 |
(42,) | tuple | 有逗号,单元素元组 |
bool(()) | False | 空元组为假 |
bool((0,)) | True | 非空即真 |
1.8、性能对比
构造方式 | 时间复杂度 | 额外内存 | 备注 |
字面量 (1, 2, 3) | O(1) | 0 | 字节码直接生成 |
tuple(iterable) | O(n) | O(n) | 需要遍历一次 |
生成器表达式 | O(n) | 0(惰性) | 无中间列表 |
1.9、线程安全
元组 不可变,天然线程安全,可作为
dict
键或 set
元素。2、公共功能
2.1、运算符 +
使用运算符 + 连接多个元组
2.2、运算符 *
使用运算符 * 将元组的元素重复
2.3、索引(下标)取值
2.4、切片取值
- 和列表一样,元组也可以切片
- 使用语法:元组\[start : end : step],获取元组中在 [start, end) 范围的子元组
- 注意范围 [start, end) 包含 start,不包含 end
- step 是步长,设为 n,则每隔 n 个元素获取一次
2.5、关键字 in
通过关键字 in 检查元组中是否包含指定元素,返回 bool 值
not in 则是取反
📝 range 对象
range
是一个 不可变序列,用来生成 等差整数序列。它既节省内存又支持随机访问,是 for 循环 和 索引切片 最常用的工具之一1、构造方法
仅限位置参数,无关键字参数。
三种重载在 CPython 中最终都会归一到 (start, stop, step) 三元组。
2、参数语义与默认值
形参 | 类型 | 默认值 | 说明 |
start | int | 0 | 序列起始值(包含) |
stop | int | — 必填 | 序列终止值(不包含) |
step | int | 1 | 步长,可为负;不能为 0 |
- 若
step
为负,序列 递减。
- 所有参数必须是 整数(Python 3 起拒绝 float)。
3、返回值
range 对象(lazy):不立即生成列表,仅保存
(start, stop, step)
。支持 索引、切片、len()、成员检测且均为 O(1)。
要得到列表需显式转换:
list(range(...))
,复杂度 O(n)。4、行为示例
5、性能与内存
- 存储仅需 3 个整数(start, stop, step),与长度无关。
len(range)
计算为 max(0, (stop-start+step-1)//step),O(1)。
- 遍历速度接近 C 级循环,比生成器更快。
6、常见误区
错误写法 | 原因 |
range(5.0) | TypeError: 'float' object cannot be interpreted as an integer |
range(5, 10, 0) | ValueError: step argument must not be zero |
range(10)[10] | IndexError: range object index out of range |
7、==、!= 操作
使用 == 和 != 检测 range 对象是否相等是将其作为序列来比较。也就是说,如果两个 range 对象表示相同的值序列就认为它们是相等的。(请注意比较结果相等的两个 range 对象可能会具有不同的start, stop和step 属性,例如 range(0) == range(2, 1, 3) 而 range(0, 3, 2) == range(0, 4, 2)。)