Python 中的列表和元组有什么区别?
核心区别
列表(list) | 元组(tuple) | |
|---|---|---|
| 语法 | [1, 2, 3] | (1, 2, 3) |
| 可变性 | ✅ 可变(增删改) | ❌ 不可变 |
| 哈希 | ❌ 不可哈希 | ✅ 可哈希(元素均不可变时) |
| 内存占用 | 较大 | 较小 |
| 性能 | 稍慢 | 稍快 |
| 用途 | 同类型的动态数据集合 | 异构的固定数据记录 |
可变性对比
lst = [1, 2, 3]
lst[0] = 99 # ✅ 可以修改
lst.append(4) # ✅ 可以追加
lst.pop() # ✅ 可以删除
tup = (1, 2, 3)
tup[0] = 99 # ❌ TypeError: 'tuple' object does not support item assignment
内存与性能
import sys
lst = [1, 2, 3, 4, 5]
tup = (1, 2, 3, 4, 5)
print(sys.getsizeof(lst)) # 104 字节
print(sys.getsizeof(tup)) # 80 字节
元组在 CPython 中有常量折叠优化,字面量元组的创建比列表快:
import timeit
print(timeit.timeit("[1, 2, 3]", number=10_000_000)) # ~0.5s
print(timeit.timeit("(1, 2, 3)", number=10_000_000)) # ~0.05s(快约 10 倍)
哈希性:可用作字典键或集合元素
# 元组可哈希,可作字典键
d = {(1, 2): "point A", (3, 4): "point B"}
s = {(1, 2), (3, 4)}
# 列表不可哈希
d = {[1, 2]: "error"} # ❌ TypeError: unhashable type: 'list'
注意:含有可变元素的元组也不可哈希:
t = ([1, 2], 3)
hash(t) # ❌ TypeError: unhashable type: 'list'
单元素的写法
lst = [1] # 列表,正常写法
tup = (1,) # 元组,必须加逗号
tup_wrong = (1) # ❌ 这只是整数 1,不是元组
print(type((1,))) # <class 'tuple'>
print(type((1))) # <class 'int'>
解包(两者均支持)
a, b, c = [1, 2, 3] # 列表解包
x, y, z = (4, 5, 6) # 元组解包
# 元组常用于函数多返回值
def get_range(data):
return min(data), max(data) # 隐式返回元组
lo, hi = get_range([3, 1, 4, 1, 5])
print(lo, hi) # 1 5
命名元组:兼具可读性和元组性能
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y) # 3 4(可按名称访问)
print(p[0], p[1]) # 3 4(也可按索引访问)
print(isinstance(p, tuple)) # True
选型建议
| 场景 | 推荐 |
|---|---|
| 存储同类型的动态集合(如用户列表) | list |
| 存储固定的异构记录(如坐标、RGB) | tuple |
| 需要作为字典键或放入集合 | tuple |
| 函数返回多个值 | tuple(隐式) |
| 需要频繁增删元素 | list |
总结
- 列表:可变、适合动态数据,用
[] - 元组:不可变、内存更小、可哈希,用
() - 不可变性使元组天然线程安全,也让 Python 对其做更多优化
- 区分两者的关键不只是"可不可以改",更是语义:列表表示"一组同类数据",元组表示"一条固定记录"