核心篇 · Core
lv.1 入门
kp-009
列表与元组
1. 一句话定义
list 是可变的有序序列,tuple 是不可变的有序序列;两者共享同一套索引/切片语法,差异全部来自"可不可以原地改"。
2. 为什么重要
list/tuple 是 Python 中最常打交道的数据组织方式。何时用谁不是审美问题:tuple 表达"结构固定的一组值"(坐标、记录),list 表达"可增删的集合",这个语义选择会被类型检查器、哈希能力、接口约束放大。
3. 前置知识
4. 核心概念
- 创建:
lst = [1, 2]、tuple_ = (1, 2);单元素 tuple 必须带逗号(1,)。 - 切片语法同源:
seq[a:b:c],产生新对象(浅拷贝)。 - list 专属操作:
append/pop/insert/extend/remove/sort/reverse(原地,返回 None!)、copy()、sorted(lst)(返回新列表)。 - 解包:
a, b = (1, 2);星号收集first, *rest = lst。
5. 原理与机制
python
lst = [3, 1, 2]
s = lst.sort() # ✗ s 是 None!sort/sort 类方法原地修改不返回
lst = sorted([3,1,2]) # ✓ sorted() 返回新列表
t = (1, 2, 3)
a, *rest = t # a=1, rest=[2,3]
x, y = y, x # 元组解包实现交换
data = [("amy", 90), ("bob", 75)]
sorted(data, key=lambda p: p[1], reverse=True) # 按分数降序tuple 不可变但元素可变:t = (1, [2]) 中 t[1].append(3) 合法——tuple 冻结的是"引用槽位",不是引用的对象。
6. 关键事实(模型/图示)
text
原地修改(返回 None): append insert extend pop remove sort reverse
返回新对象: sorted() + 拼接 切片 lst.copy() list()性能:list 底层是动态数组,尾部 append/pop 均摊 O(1),头插/任意位插入 O(n)——频繁头部操作换 collections.deque(kp-022)。
7. 直观类比
list 像活页夹:随时插页抽页,页码(下标)会因插入而变化;tuple 像装订成册的试卷:页序固定,可以作为整体贴标签(作 dict 键)、放进书架(进 set)。
8. 实例与案例
python
# 取列表 top-N
import heapq
heapq.nlargest(3, [5, 1, 9, 7]) # [9, 7, 5]
# 返回多条数据用元组(调用方解包)
def minmax(seq):
return min(seq), max(seq)
lo, hi = minmax([3, 1, 4])9. 常见误区
sort()与sorted()混用 —— 一个原地返回 None,一个返回新列表;lst = lst.sort()直接把列表变成 None。- 单元素 tuple 忘写逗号 ——
(1)是整数 1,(1,)才是元组。 - 以为
lst[:]是"安全的复制" —— 它是浅拷贝,嵌套的可变对象仍共享(见 kp-028)。 *解包后的 rest 总是 list —— 即使源是 tuple,收集结果也是 list。
10. 自测题
[1,2,3][::-1]与list(reversed([1,2,3]))的区别是什么?t = ([1], 2)能否做 dict 的键?为什么?- 如何在循环里安全地边遍历边"删除"元素?
参考答案
- 结果值相同,都返回反转新列表;
[::-1]是切片语法糖,reversed()返回迭代器需 list() 具体化。 - 不能。tuple 含可变元素导致整体不可哈希(哈希时会因遇到 list 报 TypeError)。
- 遍历副本
for x in lst[:]或列表推导式重建——不要对原列表边遍历边删。
11. 与其他知识点的关系
12. 延伸阅读
- Python 官方教程 §5 Data Structures
- Fluent Python 第 2 章(Sequence 协议)