列表能改,元组不能?
其实它不只是“只读列表”,更是 哈希钥匙 + 记录载体 + 闪电迭代器!
5 分钟,带你拆完 元组特性 → 拆包 → 性能 → 面试陷阱🔧
1️⃣ 元组长啥样?一眼记住👀
t = (1, 2, 3) # 正常
single = (42,) # 单元素必须带逗号!
empty = () # 空元组
不带逗号就是普通括号:
type((42)) # int
2️⃣ 核心特点:3 个词背下来📝
| 特点 | 说明 | 对比 list |
|---|---|---|
| 不可变 | 不能增删改 | list 可 append/pop |
| 可哈希 | 能当 dict/set 键 | list 不行 |
| 顺序 | 保留插入顺序 | 同 list |
3️⃣ 常用操作:一张表速查⚡️
| 操作 | 代码 | 结果 |
|---|---|---|
| 索引 | t[0] | 1 |
| 切片 | t[::-1] | (3, 2, 1) |
| 长度 | len(t) | 3 |
| 拼接 | t + (4,) | (1, 2, 3, 4) |
| 重复 | (0,) * 5 | (0, 0, 0, 0, 0) |
| 统计 | t.count(2) | 1 |
| 查找 | t.index(3) | 2 |
没有
append/extend/remove!想改→先转 list
4️⃣ 拆包艺术:一行赋值多个变量🎁
x, y, z = (1, 2, 3) # 位置拆包
a, *b, c = (1, 2, 3, 4) # a=1, b=[2,3], c=4
x, y = y, x # 交换变量无需 tmp
函数多返回值就是 tuple:
def divmod(a, b):
return a // b, a % b # 偷偷打包成 tuple
5️⃣ 可哈希 → 当 dict 键 & set 元素🔑
loc = {(116.4, 39.9): "北京",
(121.5, 31.2): "上海"}
base = {(1, 2), (3, 4)} # set of tuple
list 当键会抛
TypeError: unhashable type: 'list'
6️⃣ 性能对比:比 list 快 & 省内存🚀
import sys, timeit
lst = [1, 2, 3, 4, 5]
tup = (1, 2, 3, 4, 5)
sys.getsizeof(lst) # 104 bytes
sys.getsizeof(tup) # 80 bytes ↓23%
timeit.timeit('x[2]', globals={'x': lst}) # 28 ns
timeit.timeit('x[2]', globals={'x': tup}) # 22 ns ↓21%
迭代、索引、哈希都略快,大数据遍历优先 tuple
7️⃣ 嵌套元组:里面的列表可变🌟
t = (1, [2, 3], 4)
t[1].append(4) # OK → (1, [2, 3, 4], 4)
t[0] = 9 # TypeError!不能改顶层
“元组本身不可变,但元素若是可变对象→元素可以改”
8️⃣ 命名元组:可读的“小结构体”📖
from collections import namedtuple
Point = namedtuple('Point', 'x y')
p = Point(11, 22)
print(p.x, p.y) # 11 22
比 dict 省内存,可哈希,字段固定。
9️⃣ 面试陷阱 3 连击🎯
- 单元素写法
t = (5)是 int!正确:(5,) - 哈希性
问:list 能当 dict 键吗?→ 不能,unhashable - 拆包维度
a, b = (1, 2, 3)→ ValueError:too many values
🏁 口诀总结(背它!)
“圆括号是壳,逗号才是魂;
不可变可哈希,拆包多回程;
**比列表更快,当键稳如山!”**⛰️