yok*_*010 3 python operators variable-assignment
我在python中声明了四个变量[a = 1,b = 2,c = 3,d = 0],并使用','和'='(简单赋值运算符)将它们换成一行代码.
我有多个答案,并感到困惑.请帮我...
情况1:
a=1
b=2
c=3
d=0
a=a,b=b,c
print "a = " + str(a)
print "b = " + str(b)
print "c = " + str(c)
print "d = " + str(d)
Run Code Online (Sandbox Code Playgroud)
案例1的输出:
a = 2
b = 3
c = 3
d = 0
Run Code Online (Sandbox Code Playgroud)
案例2:
a=1
b=2
c=3
d=0
b=a,b=b,c
print "a = " + str(a)
print "b = " + str(b)
print "c = " + str(c)
print "d = " + str(d)
Run Code Online (Sandbox Code Playgroud)
案例2的输出:
a = 2
b = 3
c = 3
d = 0
Run Code Online (Sandbox Code Playgroud)
案例3:
a=1
b=2
c=3
d=0
c=a,b=b,c
print "a = " + str(a)
print "b = " + str(b)
print "c = " + str(c)
print "d = " + str(d)
Run Code Online (Sandbox Code Playgroud)
案例3的输出:
a = 2
b = 3
c = (2,3)
d = 0
Run Code Online (Sandbox Code Playgroud)
案例4:
a=1
b=2
c=3
d=0
d=a,b=b,c
print "a = " + str(a)
print "b = " + str(b)
print "c = " + str(c)
print "d = " + str(d)
Run Code Online (Sandbox Code Playgroud)
案例4的输出:
a = 2
b = 3
c = 3
d = (2,3)
Run Code Online (Sandbox Code Playgroud)
困惑是:
在第3和第4种情况下,输出是正确的(正如我预期的那样).但在数字1和2的情况下,a的值是2,b的值是3.我希望该值应该是(2,3).那我的代码有什么问题?
[我的Python版本是2.7]
Mar*_*ers 13
tl; dr:=从左到右,而不是从右到左(在评估右侧表达式之后)评估多个赋值(一行上的多个语句).
更复杂的是,你在一个令人兴奋的混合中使用元组赋值和"正常"赋值.
元组赋值使用一个赋值运算符,因此要交换两个变量,请使用:
a, b = b, a
Run Code Online (Sandbox Code Playgroud)
右侧必须评估与左侧有变量的元素数相同的元组.你做到了,所以没关系.
现在,在您的示例中,您不仅要解包元组.当左侧仅包含一个变量时,元组未解包,只是简单地分配:
a, b = 1, 2
a = b, a
Run Code Online (Sandbox Code Playgroud)
成为(2, 1).
当您在同一行上使用多个作业时,乐趣就开始了.这些是从左到右处理的.
那么,下面是一个简单的例子:
a = b = c = 1
Run Code Online (Sandbox Code Playgroud)
意味着a变1,然后b,再c.
现在我们可以了解每个案例:
a=a,b=b,c,其中a = 1,b = 2,c = 3.
这变为:evaluate b, c- > (2, 3),然后将其分配给a- > a = (2, 3).然后分配给a, b,所以a = 2,b = 3.结果:a = 2,b = 3,c = 3.
b=a,b=b,c,其中a = 1,b = 2,c = 3.
与之前的情况相同,但现在b = (2, 3)先设置,然后b = 3再次设置,与情况1相同.
c=a,b=b,c,其中a = 1,b = 2,c = 3.
右侧输入与案例1和2相同,但现在我们先设置c = (2, 3).最终的结果如预期a = 2,b = 3,c = (2, 3).
d=a,b=b,c,其中a = 1,b = 2,c = 3.
与案例3相同,但现在我们设置了d.没有惊喜.
让你感到困惑的是,在评估右侧之后,分配从左到右处理,而不是从右到左处理.
对于这样的情况,实际上最简单的方法是运行代码(包含在函数中),通过dis.dis()函数来反汇编python字节码:
>>> import dis
>>> def f(): a=a,b=b,c
...
>>> dis.dis(f)
1 0 LOAD_FAST 0 (b)
3 LOAD_GLOBAL 0 (c)
6 BUILD_TUPLE 2
9 DUP_TOP
10 STORE_FAST 1 (a)
13 UNPACK_SEQUENCE 2
16 STORE_FAST 1 (a)
19 STORE_FAST 0 (b)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
这是第一个案例; 注意在BUILD_TUPLE和DUP_TOP操作码之后(后者在堆栈上创建额外的副本以提供额外的赋值),首先发生的是STORE_FAST操作a,然后是UNPACK_SEQUENCE(元组赋值操作码),然后将结果存储到a和b.