赋值操作Python

Assignment operation Python

我是 Python 的新手,下面的问题对我来说很难理解。

a,b,c=1,2,3
a,b,c=c,a,b=b,a,c=c,b,a
print(a,b,c)

这个输出是-

(2,3,1)

但我不明白为什么不是 -

(3,2,1)

这是因为,当你这样写的时候,它的意思是——: a = c = b = c a的值变成c,c的值变成b,b的值变成c。 所以最后变量的变化发生在 b 而不是 a.

所以输出将是-:

2 3 1

不-:

3 2 1

你认为发生了什么

a, b, c = 1, 2, 3
b, a, c = c, b, a
print(a, b, c)
# 2, 3, 1
c, a, b = b, a, c
print(a, b, c)
# 2, 1, 3
a, b, c = c, a, b
print(a, b, c)
# 3, 2, 1

实际发生了什么

a, b, c = 1, 2, 3
# a, b, c = c, a, b = b, a, c = c, b, a
temp = c, b, a
a, b, c = temp
print(a, b, c)
# 3 2 1
c, a, b = temp
print(a, b, c)
# 2 1 3
b, a, c = temp
print(a, b, c)
# 2 3 1

基本上:根据c, b, a从右加载,而从左到右存储。

反汇编表达式证明了这一点:

import dis


def chained_assign():
    a, b, c = 1, 2, 3
    a, b, c = c, a, b = b, a, c = c, b, a
    return a, b, c


dis.dis(chained_assign)

输出:

  5           0 LOAD_CONST               4 ((1, 2, 3))
              2 UNPACK_SEQUENCE          3
              4 STORE_FAST               0 (a)
              6 STORE_FAST               1 (b)
              8 STORE_FAST               2 (c)

  6          10 LOAD_FAST                2 (c)
             12 LOAD_FAST                1 (b)
             14 LOAD_FAST                0 (a)
             16 BUILD_TUPLE              3
             18 DUP_TOP
             20 UNPACK_SEQUENCE          3
             22 STORE_FAST               0 (a)
             24 STORE_FAST               1 (b)
             26 STORE_FAST               2 (c)
             28 DUP_TOP
             30 UNPACK_SEQUENCE          3
             32 STORE_FAST               2 (c)
             34 STORE_FAST               0 (a)
             36 STORE_FAST               1 (b)
             38 UNPACK_SEQUENCE          3
             40 STORE_FAST               1 (b)
             42 STORE_FAST               0 (a)
             44 STORE_FAST               2 (c)

  7          46 LOAD_FAST                0 (a)
             48 LOAD_FAST                1 (b)
             50 LOAD_FAST                2 (c)
             52 BUILD_TUPLE              3
             54 RETURN_VALUE

注意第 6 行中 STORE_FASTLOAD_FAST 指令的顺序。

此处补充讨论:

  • Multiple assignment and evaluation order in Python
  • How do chained assignments work?

正如 norok 指出的那样,存储和装载发生在不同的方向。如果我们采用以下代码,我们可以看到 python 在幕后做了什么。

import dis

def foo():
    a, b, c = 1, 2, 3
    a, b, c = c, a, b = b, a, c = c, b, a

dis.dis(foo)

下面是字节码。在注释的右侧,您可以看到变量 abc 的值以及操作结束时的内存堆栈。您会看到 DUP_TOP 命令在各个步骤中取消分配,因此只有第一次加载和最后一次存储似乎可以执行任何操作。这也可以解释为什么 a, b, c = a, a, a = b, b, b = c, c, c = b, a, c = c, b, a 仍然计算为 (2, 3, 1).

                                                      # a b c stack

4           0 LOAD_CONST               4 ((1, 2, 3))  # - - - [(1, 2, 3)]
            3 UNPACK_SEQUENCE          3              # - - - [1, 2, 3]
            6 STORE_FAST               0 (a)          # 1 - - [2, 3]
            9 STORE_FAST               1 (b)          # 1 2 - [3]
           12 STORE_FAST               2 (c)          # 1 2 3 []

5          15 LOAD_FAST                2 (c)          # 1 2 3 [3]
           18 LOAD_FAST                1 (b)          # 1 2 3 [3, 2]
           21 LOAD_FAST                0 (a)          # 1 2 3 [3, 2, 1]
           24 BUILD_TUPLE              3              # 1 2 3 [(3, 2, 1)]
           27 DUP_TOP                                 # 1 2 3 [(3, 2, 1), (3, 2, 1)]
           28 UNPACK_SEQUENCE          3              # 1 2 3 [3, 2, 1, (3, 2, 1)]
           31 STORE_FAST               0 (a)          # 3 2 3 [2, 1, (3, 2, 1)]
           34 STORE_FAST               1 (b)          # 3 2 3 [1, (3, 2, 1)]
           37 STORE_FAST               2 (c)          # 3 2 1 [(3, 2, 1)]
           40 DUP_TOP                                 # 3 2 1 [(3, 2, 1), (3, 2, 1)]
           41 UNPACK_SEQUENCE          3              # 3 2 1 [3, 2, 1, (3, 2, 1)]
           44 STORE_FAST               2 (c)          # 3 2 3 [2, 1, (3, 2, 1)]
           47 STORE_FAST               0 (a)          # 2 2 3 [1, (3, 2, 1)]
           50 STORE_FAST               1 (b)          # 2 1 3 [(3, 2, 1)]
           53 UNPACK_SEQUENCE          3              # 2 1 3 [3, 2, 1]
           56 STORE_FAST               1 (b)          # 2 3 3 [2, 1]
           59 STORE_FAST               0 (a)          # 2 3 3 [1]
           62 STORE_FAST               2 (c)          # 2 3 1 []