python元组是不可变的——那么为什么我可以向它添加元素呢
我已经使用Python一段时间了,今天我正在阅读以下代码片段:python元组是不可变的——那么为什么我可以向它添加元素呢,python,tuples,immutability,Python,Tuples,Immutability,我已经使用Python一段时间了,今天我正在阅读以下代码片段: >>> a = (1,2) >>> a += (3,4) >>> a (1, 2, 3, 4) 我问自己一个问题:为什么python元组是不可变的,我可以对它们使用+=操作符(或者,更一般地说,为什么我可以修改元组)?我无法回答自己 我理解了不变性的概念,尽管元组不如列表那么流行,但元组在python中很有用。但是不可变和能够修改长度对我来说似乎是矛盾的…5也是不可变的。当您有
>>> a = (1,2)
>>> a += (3,4)
>>> a
(1, 2, 3, 4)
我问自己一个问题:为什么python元组是不可变的,我可以对它们使用+=
操作符(或者,更一般地说,为什么我可以修改元组)?我无法回答自己
我理解了不变性的概念,尽管元组不如列表那么流行,但元组在python中很有用。但是不可变和能够修改长度对我来说似乎是矛盾的…
5
也是不可变的。当您有一个不可变的数据结构时,a+=b
相当于a=a+b
,因此会创建一个新的数字、元组或任何内容
使用可变结构执行此操作时,结构会发生更改
例如:
>>> tup = (1, 2, 3)
>>> id(tup)
140153476307856
>>> tup += (4, 5)
>>> id(tup)
140153479825840
查看id
是如何更改的?这意味着它是一个不同的物体
现在有一个可更改的列表
:
>>> lst = [1, 2, 3]
>>> id(lst)
140153476247704
>>> lst += [4, 5]
>>> id(lst)
140153476247704
id
也是这样说的。您没有修改它,而是创建了一个新的元组,并更改了a
变量的内容
尝试
a[0]=a[0]+1
查看不变性是否+=
就地修改对象取决于对象。对于元组,您不会修改对象,因为如果您创建了指向同一对象的另一个变量,您可以看到:
>>> x = (1, 2)
>>> y = x
>>> x += (3, 4)
>>> y
(1, 2)
对于列表等可变对象,您将看到值发生更改,显示在其所有名称下:
>>> x = [1, 2]
>>> y = x
>>> x += [3, 4]
>>> y
[1, 2, 3, 4]
好的,我仍然不能向现有的元组中添加元素(这使它真正不可变),但是一个新的对象是在另外两个对象的基础上创建的-是这样吗?只有一件事在您的代码片段中仍然不清楚。tuple::
+=
正在使用两个元组创建第三个元组,即结果元组。似乎是这样;它与列表不同::+=
——因为如果它也这样做(并创建第三个列表),那么它是合乎逻辑的。但是lst+[4,5]
实际上执行了两次append。为什么列表::+=
不跟随元组::+=
?因为列表的+=
已经就位。更重要的是“为什么tuple
不做list
所做的事情”,答案是“它做不到”。我认为+=
操作符对每种序列类型的工作方式都是一样的。或者至少对于元组和列表。谢谢你解释这是完全不同的:)@tkoomzaaskz:“为什么不列出::+=跟随元组::+=”--好问题。对于列表
,a+=b
并不等同于a=a+b
。有些人可能会觉得困惑,但他们可能不会混淆,或没有经常混淆,如果人们将“如果代码>列表+= 没有做一个就位追加。最终的问题是当a
和b
具有“值语义”时,a+=b
和a=a+b
之间的“固有”等价性成立。但是Python变量没有值语义,它们有引用语义。也就是说,在Python中,变量指的是一个对象,它不包含值。+=
操作符的行为基于可变/不可变的东西,并且分别处于适当位置/不适当位置。谢谢。@tkoomzaaskz:实际上,+=
的行为取决于每种类型。如果一个类型定义了一个\uuu\iadd\uu
方法,Python将调用该方法;否则,它将调用\uuuu add\uuuu
(与+
使用的方法相同)。大多数不可变类型不定义\uuu iadd\uuu
,因此a+=b
与a=a+b
相同;大多数可变类型确实定义了\uuuu iadd\uuuu
,因此它在适当的位置对它们进行了变异。请参阅@ColonelPanic yes,有点类似的问题