元组不可变仅指其自身结构不可变,内部可变对象(如列表)仍可修改;含可变对象的元组不可哈希,且存在引用共享问题,深度不可变需手动实现。

元组不可变 ≠ 内部对象不可变
Python 的 tuple 不可变,指的是它自身结构不能变:元素个数、顺序、每个位置所“指向的对象引用”都不能改。但它不递归冻结内部对象。如果某个元素是 list,那这个 list 仍是独立的可变对象,它的内容(比如调用 .append() 或 .clear())完全可以修改。
报错只发生在直接改元组索引赋值时
常见错误现象是 TypeError: 'tuple' object does not support item assignment,但这个错误只在你写类似 t[0] = 100 这种试图替换元组中某个引用的操作时触发。而下面这些操作完全合法:
-
t = ([1, 2], "hello")→t[0].append(3)✅(改的是列表内容) -
t[0][0] = 99✅(改的是列表里第一个元素) -
del t[0][0]✅(删列表元素)
因为这些都没动元组本身,只是通过元组持有的引用,去操作了另一个可变对象。
哈希失败和共享引用是最容易踩的坑
含可变对象的元组无法作为字典键或集合元素:{([1], 2): "nope"} 会直接抛 TypeError: unhashable type: 'list'——不是元组的问题,是它里面那个 list 破坏了整个元组的哈希性。
另一个坑是引用共享:t = ([], 5); s = t; t[0].append("x"); print(s) 输出 (['x'], 5)。你以为 s 是副本,其实它和 t 是同一个元组对象,连带里面的列表也被共用。
想真正“冻结”嵌套结构得手动处理
Python 没有内置的深度不可变元组。如果你需要确保元组及其所有嵌套可变对象都不被修改,只能自己封装,比如用 frozenset 替代内层 list,或用 namedtuple + 自定义 __setattr__,甚至用 types.MappingProxyType 包装字典。别依赖 id() 或 is 判断“内容是否真没变”,该深比较时就得用 == 加递归检查。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











