有关 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
时,x
和 y
变得毫无用处或一无所有。
在您给出的示例中,是的,这两种方法的效果实际上是相同的,因为两者都涉及简单地将相同的引用分配给多个名称。
但是请注意,如果赋值目标中的表达式涉及更复杂的计算,则这两种方法可能不同。
例如,考虑下面的链式表达式,其中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))
后者将显示 y
从 obj
和 x
获得不同的引用。
我总是发现使用示例是理解事物的最佳方式(一般而言)。
假设我们有一个函数:
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
从这个答案: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
时,x
和 y
变得毫无用处或一无所有。
在您给出的示例中,是的,这两种方法的效果实际上是相同的,因为两者都涉及简单地将相同的引用分配给多个名称。
但是请注意,如果赋值目标中的表达式涉及更复杂的计算,则这两种方法可能不同。
例如,考虑下面的链式表达式,其中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))
后者将显示 y
从 obj
和 x
获得不同的引用。
我总是发现使用示例是理解事物的最佳方式(一般而言)。
假设我们有一个函数:
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