【问题标题】:python tuple is immutable - so why can I add elements to itpython 元组是不可变的 - 那为什么我可以向它添加元素
【发布时间】:2013-09-25 21:44:36
【问题描述】:

我已经使用 Python 有一段时间了,今天在阅读以下代码 sn-p 时:

>>> a = (1,2)
>>> a += (3,4)
>>> a
(1, 2, 3, 4)

我问自己一个问题:为什么 python 元组是不可变的,我可以在它们上使用 += 运算符(或者,更一般地说,为什么我可以修改元组)?而我自己也无法回答。

我理解了不变性,尽管它们不像列表那样流行,但元组在 python 中很有用。但是不可变并且能够修改长度对我来说似乎是矛盾的......

【问题讨论】:

标签: python tuples immutability


【解决方案1】:

5 也是不可变的。当你有一个不可变的数据结构时,a += b 等同于a = a + b,所以会创建一个新的数字、元组或其他任何东西。

当使用可变结构执行此操作时,结构会更改

例子:

>>> tup = (1, 2, 3)
>>> id(tup)
140153476307856
>>> tup += (4, 5)
>>> id(tup)
140153479825840

看看id 是如何变化的?这意味着它是一个不同的对象。

现在有一个list,它是可变的:

>>> lst = [1, 2, 3]
>>> id(lst)
140153476247704
>>> lst += [4, 5]
>>> id(lst)
140153476247704

id 也是这么说的。

【讨论】:

  • 好的,所以我仍然无法将元素添加到现有元组(这使得它真正不可变),但是基于另外两个对象创建了一个新对象 - 对吗?
  • 只有一件事在您的 sn-ps 中还不清楚。 tuple::+= 使用两个元组来创建第三个元组,即结果元组。似乎它与 list::+= 不同 - 因为如果它会这样做(并创建第三个列表)是合乎逻辑的。但lst + [4,5] 实际上会追加两次。为什么list::+= 不关注tuple::+=
  • 因为list+= 已就位。更多的是“为什么tuple不做list做的事情”,答案是“它不能”。
  • 我认为+= 运算符对每种序列类型的工作方式相同。或者至少对于元组和列表。感谢您解释它完全不同:)。
  • @tkoomzaaskz:“为什么不 list::+= follow tuple::+=" - 好问题。对于lista += b等同于a = a + b。有些人可能会认为这令人困惑,但他们可能不会像list+= 没有 进行就地附加时那样困惑或经常感到困惑。最终的问题是当ab 具有“值语义”时,a += ba = a + b 之间的“固有”等价性成立。但是 Python 变量没有值语义,它们有引用语义。也就是说,在 Python 中,一个变量是指一个对象,它不包含值。
【解决方案2】:

+= 是否就地修改对象取决于对象。使用元组,您不会修改对象,因为您可以看到是否创建了另一个指向同一对象的变量:

>>> x = (1, 2)
>>> y = x
>>> x += (3, 4)
>>> y
(1, 2)

对于诸如列表之类的可变对象,您会看到值发生了变化,并显示在其所有名称下:

>>> x = [1, 2]
>>> y = x
>>> x += [3, 4]
>>> y
[1, 2, 3, 4]

【讨论】:

  • 根据您的回答,+= 运算符的行为基于可变/不可变事物,分别是就地/非就地。谢谢。
  • @tkoomzaaskz:实际上,+= 的行为取决于每种类型。如果一个类型定义了一个__iadd__ 方法,Python 会调用它;否则,它将调用__add__(与+ 使用的方法相同)。大多数不可变类型没有定义__iadd__,所以a += ba = a + b 相同;大多数可变类型确实定义了__iadd__,因此它会就地改变它们。
【解决方案3】:

您没有修改它,您创建了一个新元组并更改了 a 变量的内容

尝试a[0] = a[0] + 1 来查看不变性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 2012-04-03
    • 2020-06-11
    相关资源
    最近更新 更多