有关 a=b=c 工作原理的详细信息

Details about how a=b=c works

从这个答案:How do chained assignments work?,我了解到 Python 中的链式赋值:

x = y = z      # (1)

相当于:

temp = z
x = temp
y = temp

但是 (1) 是否也等同于:

x = z
y = x

或者有细微差别(例如 z = some_function() 时)?如果有,有什么区别?

就链接和使用先前变量而言,您展示的这 2 种方法既实用又合法。完全没有区别

当将变量分配给相同数量的变量时,而不是做典型的:

x = 0
y = 0

或使用元组解包方法:

(x,y) = 0,0

你可以像你所拥有的那样做(链式作业):

x = y = 0

这可以用于 RHS 的任何对象(被调用),并且:

x = y = some_object() 

等同于:

tmp = some_object()
x = tmp
y = tmp

并且当你 del tmp 时,xy 变得毫无用处或一无所有。

在您给出的示例中,是的,这两种方法的效果实际上是相同的,因为两者都涉及简单地将相同的引用分配给多个名称。

但是请注意,如果赋值目标中的表达式涉及更复杂的计算,则这两种方法可能不同。

例如,考虑下面的链式表达式,其中x被初始化为一个字典,expensive_func是一个耗时的函数,returns一个键:

x[expensive_func()] = y = some_function()

虽然它确实等同于以下内容:

temp = some_function()
x[expensive_func()] = temp
y = temp

它不等同于第二种方法:

x[expensive_func()] = some_function()
y = x[expensive_func()]

因为 expensive_func 必须被调用两次,花费的时间加倍,并触发函数的副作用两次,如果有的话。

此外,请考虑以下代码:

obj = []
x = []
x[:] = y = obj
print(id(obj), id(x), id(y))

其中输出显示 y 被分配了与 obj 相同的引用,而 x 不同。

该代码确实等同于:

obj = []
x = []
temp = obj
x[:] = temp
y = temp
print(id(obj), id(x), id(y))

但不等同于:

obj = []
x = []
x[:] = obj
y = x[:]
print(id(obj), id(x), id(y))

后者将显示 yobjx 获得不同的引用。

我总是发现使用示例是理解事物的最佳方式(一般而言)。

假设我们有一个函数:

def function_sample ():
  print(20)

如果打印:

print(function_sample)

<function function_sample at 0x7f8f840a01f0>

return函数对象。

当给一个变量赋值一个没有括号的函数时(没有 calling/running 它)。

x = function_sample
print(x)

您将收到相同的消息:<function function_sample at 0x7f8f840a01f0>

但是,如果你 运行 它(带括号)。

print(x())

你会看到:

20
None

为什么None?这是因为 Python 函数有一个默认的 return 值,如果没有给出 return 表达式,则默认值为 None,或者单独给出 return。

另一个示例:

def another_sample(some):
  print(some)

y = another_sample
print(y)

你可能已经猜到了: <function another_sample at 0x7f8f7e747700>

如果你尝试打印 y() 你会得到一个错误,因为缺少 some 参数。

但是如果我们加一个:

print(y(5))

5
None

最后一个例子:

def third_sample ():
  return 20

aa = third_sample    # without running the func
bb = third_sample()  # calling/running the func

print(aa) # function object
print(bb) # 20