以下面的代码为例:
t=(1,2,3)
t+=(4,)
print(t)
打印的值是(1,2,3,4)。元组t的值是否刚刚更改,类似于列表对象的添加/扩展方法?
答案 0 :(得分:5)
您可以连接元组为新的元组。您将t
的值完全替换为新值。您不能修改现有的元组。为了说明:
t = (1, 2, 3)
u = t
t += (4,) # shorthand for t = t + (4,)
t == u # False
t is u # False
t
和u
不再引用同一对象。
对于可变数据结构,情况并非如此:
t = [1, 2, 3]
u = t
t.append(4)
t == u # True
t is u # True
答案 1 :(得分:3)
组是不可变的。那就是它们不能像python中的列表一样进行更改。 您正在做的只是用新的元组替换旧的元组。
答案 2 :(得分:3)
t += (4,)
或多或少是语法糖。转换为
t = t.__iadd__((4,))
(假设此方法存在。如果不存在,则退回到t = t + (4,)
)。由于元组是不可变的,因此充其量__iadd__
最多会返回绑定到旧名称t
的新元组。对于具有类似设置的列表,返回的列表将是原始的(变异的)。
答案 3 :(得分:0)
您正在做的是将一个新的元组对象重新分配给变量t
。您没有修改同一对象。
让我们开始反汇编代码。
请参阅以下内容(在第二块(STORE_FAST
中注意 85
)):
import dis
def tup_concat():
t = (1, 2, 3)
t += (4,)
print(t)
84 0 LOAD_CONST 1 ((1, 2, 3))
2 STORE_FAST 0 (t)
85 4 LOAD_FAST 0 (t)
6 LOAD_CONST 2 ((4,))
8 INPLACE_ADD
10 STORE_FAST 0 (t)
86 12 LOAD_GLOBAL 0 (print)
14 LOAD_FAST 0 (t)
16 CALL_FUNCTION 1
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
但是,如果您真正地修改了一个对象(例如列表),它将看起来像这样:
import dis
def modify():
t = [4,6,7]
t.append(4)
dis.dis(modify)
89 0 LOAD_CONST 1 (4)
2 LOAD_CONST 2 (6)
4 LOAD_CONST 3 (7)
6 BUILD_LIST 3
8 STORE_FAST 0 (t)
90 10 LOAD_FAST 0 (t)
12 LOAD_METHOD 0 (append)
14 LOAD_CONST 1 (4)
16 CALL_METHOD 1
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
注意:第二块(STORE_FAST
)中没有 90
。
结论:不引用同一对象(t
之前和之后的变量INPLACE_ADD
)。