引自某事:
>>> x = y = somefunction()
与
相同>>> y = somefunction()
>>> x = y
问题:是
x = y = somefunction()
与
相同x = somefunction()
y = somefunction()
根据我的理解,它们应该相同,因为somefunction
只能返回一个值。
答案 0 :(得分:41)
都不是。
x = y = some_function()
相当于
temp = some_function()
x = temp
y = temp
请注意订单。 首先分配最左边的目标。 (may中的C opposite order中的类似表达式。)来自Python assignment上的文档:
...从左到右将单个结果对象分配给每个目标列表。
反汇编显示:
>>> def chained_assignment():
... x = y = some_function()
...
>>> import dis
>>> dis.dis(chained_assignment)
2 0 LOAD_GLOBAL 0 (some_function)
3 CALL_FUNCTION 0
6 DUP_TOP
7 STORE_FAST 0 (x)
10 STORE_FAST 1 (y)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
注意:same object始终分配给每个目标。所以@Wilduck和@andronikus指出,你可能永远不会想要这个:
x = y = [] # Wrong.
在上面的情况中,x和y表示相同的列表。由于列表为mutable,因此附加到x将seem to affect y。
x = [] # Right.
y = []
现在你有两个名字引用两个不同的空列表。
答案 1 :(得分:35)
如果somefunction
返回可变值,它们不一定会起作用。考虑:
>>> def somefunction():
... return []
...
>>> x = y = somefunction()
>>> x.append(4)
>>> x
[4]
>>> y
[4]
>>> x = somefunction(); y = somefunction()
>>> x.append(3)
>>> x
[3]
>>> y
[]
答案 2 :(得分:13)
如果somefunction()
每次调用时返回不同的值,该怎么办?
import random
x = random.random()
y = random.random()
答案 3 :(得分:4)
在
x = somefunction()
y = somefunction()
somefunction
将被调用两次而不是一次。
即使每次都返回相同的结果,如果返回结果需要一分钟,这将是一个明显的问题! 或者如果它有副作用,例如询问用户他的密码。
答案 4 :(得分:4)
E.g:
def is_computer_on():
return True
x = y = is_computer_on()
或
def get_that_constant():
return some_immutable_global_constant
请注意,结果将是相同的,但实现结果的过程不会:
def slow_is_computer_on():
sleep(10)
return True
x和y变量的内容相同,但指令x = y = slow_is_computer_on()
将持续10秒,而其对应x = slow_is_computer_on() ; y = slow_is_computer_on()
将持续20秒。
E.g:
def count_three(i):
return (i+1, i+2, i+3)
x = y = count_three(42)
请注意,上一节中解释的相同捕获量适用。
为什么我说差不多?因此:
x = y = count_three(42)
x is y # <- is True
x = count_three(42)
y = count_three(42)
x is y # <- is False
好的,使用is
有点奇怪,但这表明回报并不相同。这对于可变的案例非常重要:
这个问题也得到了解答。为了完整起见,我重播了这个论点:
def mutable_count_three(i):
return [i+1, i+2, i+3]
x = y = mutable_count_three(i)
因为在那种情况下x
和y
是同一个对象,所以执行x.append(42)
这样的操作意味着x
和y
都会有参考现在有4个元素的列表。
考虑到打印副作用(我觉得有效,但可以使用其他示例):
def is_computer_on_with_side_effect():
print "Hello world, I have been called!"
return True
x = y = is_computer_on_with_side_effect() # One print
# The following are *two* prints:
x = is_computer_on_with_side_effect()
y = is_computer_on_with_side_effect()
而不是打印,它可能是一个更复杂或更微妙的副作用,但事实仍然是:该方法被调用一次或两次,这可能会导致不同的行为。
也许是一个简单的随机方法:
def throw_dice():
# This is a 2d6 throw:
return random.randint(1,6) + random.randint(1,6)
x = y = throw_dice() # x and y will have the same value
# The following may lead to different values:
x = throw_dice()
y = throw_dice()
但是,与时钟,全局计数器,系统内容等相关的事情对于输入是不确定的是明智的,在这些情况下x
和y
的值可能不同。
答案 5 :(得分:0)
正如鲍勃·斯坦(Bob Stein)所说,分配顺序很重要;看一下以下非常有趣的情况:
L = L[1] = [42, None]
现在,什么包含L
?您必须了解,最初分配给[42, None]
的单个对象是L
;最后,执行类似L[1] = L
的操作。因此,您创建了一些循环的无限“列表”(此处的“列表”一词与Lisp中的某些CONS
类似,标量42
为CAR
,列表本身为CDR
。
只需输入:
>>> L
[42, [...]]
然后输入L[1]
,然后依次输入L[1][1]
和L[1][1][1]
,直到结束为止,都会很有趣。
该示例比其他答案中的其他示例更难以理解,但另一方面,您可以更快地看到它
L = L[1] = [42, None]
与
不同L[1] = L = [42, None]
因为如果先前未定义L
,则第二个将引发异常,而第一个将始终有效。