【问题标题】:Multiple assignment and evaluation order in PythonPython中的多重赋值和评估顺序
【发布时间】:2012-02-02 06:49:00
【问题描述】:

以下 Python 表达式有什么区别:

# First:

x,y = y,x+y

# Second:

x = y
y = x+y

First 给出的结果与 Second 不同。

例如,

第一:

>>> x = 1
>>> y = 2
>>> x,y = y,x+y
>>> x
2
>>> y
3

第二个:

>>> x = 1
>>> y = 2
>>> x = y
>>> y = x+y
>>> x
2
>>> y
4

y 是 First 中的 3 和 Second 中的 4

【问题讨论】:

    标签: python variable-assignment assignment-operator multiple-assignment


    【解决方案1】:

    在赋值语句中,总是在进行变量的实际设置之前完全评估右侧。所以,

    x, y = y, x + y
    

    评估y(我们称结果为ham),评估x + y(称其为spam),然后将x设置为ham和y spam。也就是说,就像

    ham = y
    spam = x + y
    x = ham
    y = spam
    

    相比之下,

    x = y
    y = x + y
    

    将x 设置为y,然后将y 设置为x(== y)加上y,所以它相当于

    x = y
    y = y + y
    

    【讨论】:

    • 为了与代码库中可能发现的类似语法相关,x,y = y,x+y 与 (x,y) = y,x+y 相同,因此括号是不必要的。听起来对吗?
    • @jxramos 是的,括号是不必要的,但这更多是关于元组的问题。
    【解决方案2】:

    在标题为"Evaluation order"的部分的文档中进行了解释:

    ...在评估分配时,评估右侧 在左侧之前。

    【讨论】:

      【解决方案3】:

      第一个表达式:

      1. 创建一个临时元组,其值为y,x+y
      2. 分配到另一个临时元组
      3. 将元组提取到变量x 和y

      第二条语句实际上是两个表达式,没有元组的用法。

      惊喜的是,第一个表达式居然是:

      temp=x
      x=y
      y=temp+y
      

      您可以在“Parenthesized forms”中了解更多关于逗号的用法。

      【讨论】:

        【解决方案4】:

        我最近开始使用 Python,这个“功能”让我感到困惑。虽然给出了很多答案,但我还是会发布我的理解。

        如果我想交换两个变量的值,在 JavaScipt 中,我会执行以下操作:

        var a = 0;
        var b = 1;
        
        var temp = a;
        a = b;
        b = temp;
        

        我需要第三个变量来临时保存其中一个值。一个非常简单的交换是行不通的,因为这两个变量最终会得到相同的值。

        var a = 0;
        var b = 1;
        
        a = b; // b = 1 => a = 1
        b = a; // a = 1 => b = 1
        

        想象一下,有两个不同的(红色和蓝色)桶,里面分别有两种不同的液体(水和油)。现在,尝试交换桶/液体(蓝色桶中的水和红色桶中的油)。除非你有一个额外的桶,否则你不能这样做。

        Python 用一种“更干净”的方式/解决方案来处理这个问题:Tuple Assignment。

        a = 0
        b = 1
        
        print(a, b) # 0 1
        
        # temp = a
        # a = b
        # b = temp
        
        a, b = b, a # values are swapped
        
        print(a, b) # 1 0
        

        我猜,这样 Python 会自动创建“临时”变量,我们不必担心它们。

        【讨论】:

        • 就像链接中提到的“右侧的所有表达式都在任何分配之前进行评估”。感谢您的澄清。
        【解决方案5】:

        关于左侧的观察:分配的顺序保证是它们出现的顺序,换句话说:

        a, b = c, d
        

        在功能上等同于精确(除了 t 创建):

        t = (c, d)
        a = t[0] # done before 'b' assignment
        b = t[1] # done after 'a' assignment
        

        这在对象属性分配等情况下很重要,例如:

        class dummy:
            def __init__(self): self.x = 0
        
        a = dummy(); a_save = a
        a.x, a = 5, dummy()
        print(a_save.x, a.x) # prints "5 0" because above is equivalent to "a = dummy(); a_save = a; t = (5, dummy()); a.x = t[0]; a = t[1]"
        
        a = dummy(); a_save = a
        a, a.x = dummy(), 5
        print(a_save.x, a.x) # prints "0 5" because above is equivalent to "a = dummy(); a_save = a; t = (dummy(), 5); a = t[0]; a.x = t[1]"
        

        这也意味着您可以使用单行代码执行对象创建和访问等操作,例如:

        class dummy:
            def __init__(self): self.x = 0
        # Create a = dummy() and assign 5 to a.x
        a, a.x = dummy(), 5
        

        【讨论】:

          【解决方案6】:

          在第二种情况下,您将x+y 分配给x

          第一种情况,第二个结果(x+y)赋值给y

          这就是您获得不同结果的原因。

          修改后

          发生这种情况是因为,在声明中

          x,y = y,x+y
          

          右侧成员的所有变量都被评估,然后存储在左侧成员中。所以first继续处理右边的成员,second处理左边的成员。

          在第二个语句中

          x = y
          y = x + y
          

          你首先评估y并将其分配给x;这样,x+y 的总和等于 y+y 的总和,而不是 x+x 的总和,这是第一种情况。

          【讨论】:

            【解决方案7】:

            第一个是类似元组的赋值:

            x,y = y,x+y
            

            其中x 是元组的第一个元素,y 是第二个元素,因此您要做的是:

            x = y
            y = x+y
            

            而第二个是直接分配:

            x=y
            x=x+y
            

            【讨论】:

              【解决方案8】:

              其他答案已经解释了它是如何工作的,但我想添加一个非常具体的例子。

              x = 1
              y = 2
              x, y = y, x+y
              

              在最后一行中,首先像这样取消引用名称:

              x, y = 2, 1+2
              

              然后计算表达式:

              x, y = 2, 3
              

              然后元组展开,然后发生赋值,相当于:

              x = 2; y = 3
              

              【讨论】:

                【解决方案9】:

                对于新手,我遇到了一个可以帮助解释这一点的示例:

                # Fibonacci series:
                # the sum of two elements defines the next
                a, b = 0, 1
                while a < 10:
                    print(a)
                    a, b = b, a+b
                

                通过多重赋值,将初始值设置为a=0,b=1。 在 while 循环中,两个元素都被赋予了新的值(因此称为“多重”赋值)。将其视为 (a,b) = (b,a+b)。所以在循环的每次迭代中 a = b, b = a+b。这将继续,而

                结果: 0 1 1 2 3 5 8

                【讨论】:

                  【解决方案10】:

                  让我们了解一下不同之处。

                  x, y = y, x + y 是x元组xssignment,mexns(x, y) = (y, x + y),就像(x, y) = (y, x)

                  来自 x 的 Stxrt 快速示例:

                  x, y = 0, 1
                  #equivxlent to
                  (x, y) = (0, 1)
                  #implement xs
                  x = 0
                  y = 1
                  

                  当谈到(x, y) = (y, x + y) ExFP,让x直接试试

                  x, y = 0, 1
                  x = y #x=y=1
                  y = x + y #y=1+1
                  #output
                  In [87]: x
                  Out[87]: 1
                  In [88]: y
                  Out[88]: 2
                  

                  然而,

                  In [93]: x, y = y, x+y
                  In [94]: x
                  Out[94]: 3
                  In [95]: y
                  Out[95]: 5
                  

                  结果与第一次尝试不同。

                  谢谢,因为 Python 首先评估右手x+y 所以它相当于:

                  old_x = x
                  old_y = y
                  c = old_x + old_y
                  x = old_y
                  y = c
                  

                  综上,x, y = y, x+y的意思是,
                  x交换得到y的old_value,
                  y交换得到旧值x和旧值y之和,

                  【讨论】:

                    【解决方案11】:
                    a, b = 0, 1
                    while b < 10:
                        print(b)
                        a, b = b, a+b
                    

                    输出

                    1
                    1
                    2
                    3
                    5
                    8
                    

                    变量a和b同时得到新值0和1,同样的a, b = b, a+b、a和b被同时赋值。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-02-06
                      • 2012-12-05
                      • 2016-02-23
                      相关资源
                      最近更新 更多