【问题标题】:In Python a tuple is immutable object but allows mutation of a contained list?在 Python 中,元组是不可变对象,但允许包含列表的突变?
【发布时间】:2016-02-05 13:23:20
【问题描述】:

在 Python 中:

>>> tup = (1,"a",[1,2,3])
>>> tup
(1, 'a', [1, 2, 3])
>>> tup[2][1] = "a"
>>> tup
(1, 'a', [1, 'a', 3])

从上面我可以修改作为元组一部分的列表内容。由于元组是不可变的,这怎么可能? 我是否以错误的方式理解了不可变部分?

【问题讨论】:

  • 因为list 总是可变的。
  • 你没有改变元组。第三个元素仍然包含对同一列表的引用。列表已更改,元组在技术上并未更改。
  • 比较 [id(x) for x in tup] 在修改包含列表之前和之后。

标签: python


【解决方案1】:

您确实以错误的方式理解了不可变部分。元组确实是不可变的,因为您无法更改其列表:

In [3]: tup[2] = []
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-02255d491606> in <module>()
----> 1 tup[2] = []

TypeError: 'tuple' object does not support item assignment

列表的引用在该元组中是不可变的。但是,列表本身是可变的,因此可以修改,如您所知。

换句话说,不可变的元组包含三个元素:

  • 整数 1
  • 字符串“a”
  • 对列表的引用

你可以把它想象成列表的地址,如果你知道C。如果你对内存一无所知,你可以把它看成“元组知道在哪里可以找到列表”。但它不包含列表本身。

【讨论】:

  • 好的,我知道 C,我现在明白 tuple 存储对列表的引用(不是我之前理解的实际值),但是一旦你选择了引用(列表) ,列表值可以修改,谢谢。
【解决方案2】:

元组容器是不可变的,但其中的元素可能不可变。

您示例中的元组确实是不可变的,但它包含对可变列表的引用

那么最后我可以修改元组的内容吗?

不,您不能使元组指向不同的列表,但您可以更改列表中的内容。

当您执行tup[2][1]="a" 时,您并没有改变元组,而是改变了列表。元组仍然具有对列表的相同引用,就像以前一样。

查看引用未更改的片段:

我们可以使用id(),它返回对象的标识(在CPython中返回对象在内存中的地址)

>>> tup = (1,"a",[1,2,3])
>>> tup
(1, 'a', [1, 2, 3])
>>> [id(x) for x in tup]
[36090200, 140119363921520, 140119362889416]
>>> tup[2][1] = 'a'
>>> tup
(1, 'a', [1, 'a', 3])
>>> [id(x) for x in tup]
[36090200, 140119363921520, 140119362889416]

【讨论】:

  • 不可变意味着内容不能被修改对吧?但是在这里我可以使用可变容器修改元组的内容,所以最后我可以修改元组的内容吗?
【解决方案3】:

元组是不可变的——它总是包含相同的对象。如果这些对象是可变的,它们本身可能会发生变异,但元组仍将包含该对象。

【讨论】:

    猜你喜欢
    • 2020-11-13
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2018-02-27
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多