Python中的多个赋值和求值顺序

时间:2012-01-04 10:57:39

标签: python assignment-operator

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

# First:

x,y = y,x+y

# Second:

x = y
y = x+y

第一个提供的结果与 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 第一中为3,在第二

中为4

11 个答案:

答案 0 :(得分:68)

在赋值语句中,在执行变量的实际设置之前,始终会完全评估右侧。所以,

x, y = y, x + y

评估y(让我们调用结果ham),评估x + y(调用spam),然后设置{{1} } xhamy。即,就像

spam

相比之下,

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

x = y y = x + y 设置为x,然后将y设置为yx)加== y,这相当于

y

答案 1 :(得分:11)

在标题为"Evaluation order"

的部分的文档中对此进行了解释
  

...在评估作业时,评估右侧   在左手边之前。

答案 2 :(得分:4)

第一个表达:

  1. 创建值为y,x+y
  2. 的临时元组
  3. 分配给另一个临时元组
  4. 将元组提取为变量xy
  5. 第二个语句实际上是两个表达式,没有使用元组。

    令人惊讶的是,第一个表达式实际上是:

    temp=x
    x=y
    y=temp+y
    

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

答案 3 :(得分:1)

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

在第一种情况下,第二个结果(x+y)被分配到y

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

修改后

这是因为,在声明中

x,y = y,x+y

评估右侧成员的所有变量,然后将其存储在左侧成员中。所以第一个继续使用正确的成员,第二个继续使用左成员。

在第二个陈述中

x = y
y = x + y

首先评估y并将其分配给x;这样,x+y的总和相当于y+y的总和而不是x+x的总和。

答案 4 :(得分:1)

第一个是类似元组的任务:

x,y = y,x+y

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

x = y
y = x+y

第二个是直接分配:

x=y
x=x+y

答案 5 :(得分:1)

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

# 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。这会持续到<10。

结果: 0 1个 1个 2 3 5 8

答案 6 :(得分:0)

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同时分配。

答案 7 :(得分:0)

让我们了解不同之处。

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的总和,

答案 8 :(得分:0)

我最近开始使用Python和这个&#34;功能&#34;困惑我。虽然给出了很多答案,但无论如何我都会发表我的理解。

如果我想交换两个变量的值,请在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使用&#34;清洁剂&#34;方式/解决方案: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创建&#34; temp&#34;变量是自动的,我们不必担心它们。

答案 9 :(得分:0)

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

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

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

x, y = 2, 1+2

然后对表达式求值:

x, y = 2, 3

然后展开元组,然后然后进行分配,等效于:

x = 2; y = 3

答案 10 :(得分:0)

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

a, b = c, d

在功能上与精确地等效(除了创建之外):

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