当前位置: 首页 > 面试题库 >

附加到元组中定义的列表-是bug吗?[重复]

司徒茂实
2023-03-14
问题内容

这个问题已经在这里有了答案

可变容器内的可变类型 (3个答案)

3年前关闭。

所以我有这段代码

tup = ([1,2,3],[7,8,9])
tup[0] += (4,5,6)

生成此错误:

TypeError: 'tuple' object does not support item assignment

而这段代码:

tup = ([1,2,3],[7,8,9])
try:
    tup[0] += (4,5,6)
except TypeError:
    print tup

打印此:

([1, 2, 3, 4, 5, 6], [7, 8, 9])

这是预期的行为吗?

注意

我意识到这不是一个很常见的用例。但是,虽然预期会出现错误,但我没想到列表会发生变化。


问题答案:

是的,这是预期的。

元组不能更改。元组(如列表)是指向其他对象的结构。它不在乎那些对象是什么。它们可以是字符串,数字,元组,列表或其他对象。

因此,对元组中包含的对象之一执行任何操作(包括在列表中追加到该对象)都与元组的语义无关。

(想象一下,如果您编写了一个类,该类上具有导致其内部状态发生变化的方法。您不会期望不可能根据对象的存储位置在对象上调用这些方法)。

或另一个例子:

>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> t = (l1, l2)
>>> l3 = [l1, l2]
>>> l3[1].append(7)

一个列表和一个元组引用的两个可变列表。我是否应该能够做最后一行(答案:是)。如果您认为答案是否定的,为什么不呢?应该t更改l3(答案:否)的语义。

如果您想要一个不可变的顺序结构对象,那么它应该一直是元组。

本示例使用infix运算符:

许多操作都有“就地”版本。与通常的语法相比,以下函数提供了对原位运算符的更原始的访问;例如,语句x + = y等效于x =
operator.iadd(x,y)。另一种表达方式是说z = operator.iadd(x,y)等效于复合语句z = x; z + = y。

https://docs.python.org/2/library/operator.html

所以这:

l = [1, 2, 3]
tup = (l,)
tup[0] += (4,5,6)

等效于此:

l = [1, 2, 3]
tup = (l,)
x = tup[0]
x = x.__iadd__([4, 5, 6]) # like extend, but returns x instead of None
tup[0] = x

__iadd__行成功,并修改了第一个列表。因此,列表已更改。该__iadd__调用返回的突变列表。

第二行尝试将列表分配回元组,这将失败。

因此,在程序结束时,列表已扩展,但是操作的第二部分+=失败。有关详细信息,请参阅此问题。



 类似资料:
  • 我有一个熊猫数据框,其中一列由列表组成: 我想添加,例如,每个列表的第一个和最后一个索引。为此,我使用: 这分别作用于每一行,如果数据帧很大,这可能会非常密集。有没有办法将此操作矢量化?

  • 假设我有一个元组列表,如下所示: 我想在此列表中添加另一个元组。我该怎么做? 更具体地说,我想将此元组添加为列表中的第一个元组,以便我得到: 我使用的是Python 2.7。 提前感谢!

  • 问题内容: 有没有更优雅的方式来编写此代码? 我在做什么:我有键和日期。可能有多个日期分配给键,因此我正在创建一个包含日期列表的字典来表示这一点。以下代码可以正常工作,但是我希望有一个更优雅和Pythonic的方法。 我期望下面的工作,但我不断得到一个NoneType没有属性附加错误。 这可能与以下事实有关: 但为什么? 问题答案: 返回,因为它是就地操作,并且您将其分配回。因此,下一次您实际要做

  • 给一本字典: 如何将键附加到列表中? 我走了这么远:

  • 我想要一个列表,它是列表元素列表的组合,例如:我的输入 输出应该是 非常感谢您的帮助。

  • 问题内容: 我有一个类似于以下的元组列表: 我想创建一个简单的单线,这将给我以下结果: 就像执行以下操作: 我相信这很简单,但是我想不到。 注意:我已经看过类似的问题: 如何在Python中的元组列表中对每个元组的第一个值求和? 问题答案: 使用和: 要么: 结果: