为什么可以为具有串联的元组分配新值?

时间:2018-10-10 09:41:50

标签: python tuples

以下面的代码为例:

t=(1,2,3)
t+=(4,)
print(t)

打印的值是(1,2,3,4)。元组t的值是否刚刚更改,类似于列表对象的添加/扩展方法?

4 个答案:

答案 0 :(得分:5)

您可以连接元组为新的元组。您将t的值完全替换为新值。您不能修改现有的元组。为了说明:

t = (1, 2, 3)
u = t
t += (4,)  # shorthand for t = t + (4,)

t == u  # False
t is u  # False

tu不再引用同一对象

对于可变数据结构,情况并非如此:

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)。