为什么元组tuple包含可变item?

问题:

如果一个元组是不可变的,那么为什么它可以包含可变项目?
似乎是一个矛盾,当可变项目如列表确实被修改时,它所属的元组维护是不可变的。

回答:

这是一个很好的问题。
关键的洞察是,元组无法知道它们内部的对象是否是可变的。使对象可变的唯一方法是具有改变其数据的方法。一般来说,没有办法检测到这个。
另一个见解是Python的容器实际上并不包含任何东西。相反,它们保持对其他对象的引用。同样,Python的变量不像编译语言中的变量;而变量名只是命名空间字典中的关键字,它们与对应的对象相关联。 Ned Batchhelder在他的blog post中很好地解释了这一点。无论哪种方式,对象只知道其引用计数;他们不知道这些引用是什么(变量,容器或Python内部)。
总而言之,这两个洞察力解释了你的谜团(为什么一个不可变的元组“包含”列表似乎在底层列表发生变化时会发生变化)。事实上,元组没有改变(它仍然具有与之前的其他对象相同的参考)。元组无法更改(因为它没有变异方法)。当列表更改时,元组没有收到更改的通知(列表不知道是否由变量,元组或其他列表引用)。
在我们讨论这个话题的同时,还有一些其他想法可以帮助你完成你的心理模型,包括什么元组,它们的工作原理和预期的用途:

  1. 元组的特征不在于它们的不变性,更多的是它们的预期目的。
    元组是Python在一个屋檐下收集异构信息的方法。例如,
    s = ('www.python.org', 80)
    汇集一个字符串和一个数字,以便主机/端口对可以作为一个套接字传递,一个复合对象。从这个角度来看,具有可变组件是完全合理的。
  2. 不变性与另一个物业hashability携手并进。但是哈希性不是绝对属性。如果其中一个元组的组件不可哈希,那么整个元组也不是可哈希的。例如,t = ('red', [10, 20, 30])不可哈希。

最后一个示例显示一个包含字符串和列表的2元组。元组本身不是可变的(即它没有任何改变其内容的方法)。同样,字符串是不可变的,因为字符串没有任何突变方法。列表对象具有突变方法,因此可以进行更改。这表明可变性是对象类型的属性 – 一些对象具有突变方法,一些对象没有。这不会因为对象被嵌套而改变。
记住两件事首先,不变性不是魔术 – 只是缺乏突变方法。第二,对象不知道什么变量或容器引用它们 – 他们只知道引用计数。
希望这对你有用:-)

Code问答: http://codewenda.com/topics/python/
Stackoverflow: Why can tuples contain mutable items?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

57 + = 60