python元组的相对不变性
《流畅的python》一书中,第186页(第8章:对象引用、可变性和垃圾回收),8.2.2 元组的相对不可变性中有以下内容:
“元组与多数python集合(列表、字典、集,等等)一样,保存的是对象的引用。如果引用的元素是可变的,即便元组本身不可变,元素依然可变。也就是说,元组的不可变性其实是指tuple数据结构的物理内容(即保存的引用)不可变,与引用的对象无关”
“示例8-5表明,元组的值会随着引用的可变对象的变化而变。元组中不可变的是元素的标识”
示例8-5:
>>>t1 = ( 1, 2, [30, 40] )
>>>t2 = ( 1, 2, [30, 40] )
>>> t1 == t2
True
>>>id( t1[-1])
4302515784
>>>t1[-1].append(99)
>>>t1
(1,2,[30,40,99])
>>>id(t1[-1])
4302515784
>>>t1==t2
False
以下是我的理解:
作者用这个例子来说明元组的不可变性实际上指元组保留的的引用不可变,也就是说,元组的不可变性是指元组要保持其元素的id值不变,而id值是在对象创建的时候生成的,(也就是说,对于一个指定的对象,如果有多个引用指向这个对象,那么这些引用的id值应该都是相等的),元组保持其元素的id值不变,那么即使元素的值发生了改变,只要其id值不变,那么元组允许这种操作,示例中t1[-1]使用append方法为元素添加了值而元组依然允许这种操作,而当我试图执行以下操作时,却遇到了问题:
>>>t1 = [1,2]
>>>t2 = t1
>>> t1 is t2
True
>>>id(t1)
4302515784
>>id(t2)
4302515784
可以看到t1和t2都是同一个对象的引用,因此他们的id值都相等
>>>tuple1 = (1,2,t1)
这里我构建了一个元组
>>>tuple[-1] = t2
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'type' object does not support item assignment
问题来了,当我试图将t2赋给tuple1[-1]时,却得到了错误。我想,既然元组的不可变性只是体现在其保持元素引用的不变,那么现在t1和t2这两个引用是相同的,他们指向同一块内存空间,他们的id值也相等,那么我在赋值的时候并没有改变元组内元素引用的值,可为什么操作就失败了?而示例中,作者对元组的元素使用append()方法添加元素也同样没有改变元组内元素的引用,他的操作却可以成功。。。