赋值操作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_FAST
和 LOAD_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)
下面是字节码。在注释的右侧,您可以看到变量 a
、b
和 c
的值以及操作结束时的内存堆栈。您会看到 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 []
我是 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_FAST
和 LOAD_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)
下面是字节码。在注释的右侧,您可以看到变量 a
、b
和 c
的值以及操作结束时的内存堆栈。您会看到 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 []