这是一个很好的问题.
关键是元组无法知道其中的对象是否是可变的.唯一能让一个对象可变的就是有一个改变其数据的方法.一般来说,没有办法检测到这一点.
另一个见解是Python的容器实际上并不包含任何内容.相反,它们保留对其他对象的引用.同样,Python的变量与编译语言中的变量不同;相反,变量名只是名称空间字典中的键,它们与相应的对象相关联.Ned Batchelder在他的blog post篇文章中很好地解释了这一点.不管怎样,对象只知道它们的引用计数;他们不知道这些引用是什么(变量、容器或Python内部).
这两个洞见一起解释了你的谜团(为什么一个"包含"列表的不可变元组在基础列表发生变化时似乎会发生变化).事实上,元组没有改变(它对其他对象的引用仍然与以前相同).元组无法更改(因为它没有变异方法).当列表更改时,元组没有收到更改通知(列表不知道它是由变量、元组还是其他列表引用).
在我们讨论这个话题时,这里有一些其他 idea 可以帮助你完成元组是什么、它们如何工作以及它们的预期用途的心智模型:
元组的特点与其说是不变性,不如说是其预期用途
不变性与另一个属性hashability密切相关.但哈希性并不是绝对属性.如果元组的一个组件不可散列,那么整个元组也不可散列.例如,t = ('red', [10, 20, 30])
是不可散列的.
最后一个示例显示了一个包含字符串和列表的2元组.元组本身是不可变的(也就是说,它没有任何改变其内容的方法).同样,字符串是不可变的,因为字符串没有任何变异方法.列表对象确实有变异方法,因此可以对其进行更改.这表明可变性是一种对象类型的属性——有些对象有变异方法,有些没有.这不会因为对象是嵌套的而改变.
记住两件事.首先,不变性不是魔术--它只是缺少变异的方法.其次,对象不知道引用它们的变量或容器--它们只知道引用计数.
希望,这对你有用:-)