python - 简单的赋值运算符在 Python 中变得复杂

标签 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)

案例 1 的输出:

a = 2
b = 3
c = 3
d = 0


案例 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)

案例 2 的输出:

a = 2
b = 3
c = 3
d = 0


案例三:

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)

案例 3 的输出:

a = 2
b = 3
c = (2,3)
d = 0


案例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)

案例 4 的输出:

a = 2
b = 3
c = 3
d = (2,3)

混淆是:

在案例 3 和案例 4 中,输出是正确的(如我所料)。但在 1 号和 2 号的情况下,a 的值为 2,b 的值为 3。我希望该值应为 (2,3)。那么我的代码有什么问题?

[我的 Python 版本是 2.7]

最佳答案

tl;dr:多重赋值(一行中的多个 = 语句)是从左到右计算的,而不是从右到左的(计算右侧表达式之后) ).

使事情复杂化的是,您正在混合使用元组赋值和“正常”赋值。

元组赋值使用一个赋值运算符,因此要交换两个变量,请使用:

a, b = b, a

右侧必须计算出一个元组,该元组的元素数量与左侧的变量数量相同。你这样做,那很好。

现在,在您的示例中,您不仅要拆包元组。当左侧仅包含一个变量时,元组不会解包,只是简单地赋值:

a, b = 1, 2
a = b, a

变成 (2, 1)

当您在同一行上使用多个 赋值时,乐趣就开始了。这些是从左到右处理的。

所以,下面这个简单的例子:

a = b = c = 1

表示 a 变为 1,然后是 b,然后是 c

现在我们可以理解每个案例了:

  1. a=a,b=b,c,其中a = 1b = 2c = 3

    这变成了:评估 b, c -> (2, 3),然后将其分配给 a -> a = (2, 3)。然后赋值给a,b,所以a = 2, b = 3。结果:a = 2b = 3c = 3

  2. b=a,b=b,c,其中a = 1b = 2c = 3

    与之前的情况相同,但现在先设置 b = (2, 3),然后再次设置 b = 3,结果与情况 1 相同。

  3. c=a,b=b,c,其中a = 1b = 2c = 3

    右侧的输入与情况 1. 和 2. 相同,但现在我们首先设置 c = (2, 3)。最终结果符合预期,a = 2b = 3c = (2, 3)

  4. d=a,b=b,c,其中a = 1b = 2c = 3

    与情况 3 相同。但现在我们改为设置 d。没有惊喜。

这里让您感到困惑的是,在计算完右侧后,分配是从左到右处理的,不是从右到左。

对于此类情况,通过 dis.dis() function 运行您的代码(包装在函数中)实际上是最简单的反汇编 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        

这是第一种情况;请注意在 BUILD_TUPLEDUP_TOP 操作码(后者在堆栈上创建一个额外的副本以服务于额外的分配)之后,发生的第一件事是 a 上的 STORE_FAST 操作,后跟 UNPACK_SEQUENCE(元组分配操作码),然后将结果存储到 ab

关于python - 简单的赋值运算符在 Python 中变得复杂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13657704/

相关文章:

c++ - 不同版本模板类的二元运算符

python - 使用 ">>"和 "&"运算符的变量赋值

c# - 关闭和引用设置

c++ - 将派生类分配给基类

Python优化问题?

python - 如何使用预训练的模型权重初始化新的 word2vec 模型?

python - 查询可选参数

python - 你如何在 Python 中舍入一个字符串?

mysql - OR 运算符忽略 AND 运算符 MYSQL

c - 算术赋值运算符 - 左侧仅计算一次