Python 语法:从三元表达式中的函数返回值中解压缩多个变量会产生意外结果



我注意到在三元表达式中解压缩多个值时存在一个奇怪的问题。首先,一个说明语法的 MWE,其目的是解压缩右侧的元组,并将其中的列表分配给左侧的第一个名称,将数字分配给第二个名称。

condition = False
a, b = [1, 2], 3 if not condition else None, None  # ValueError: too many values to unpack
def foo():
return [1, 2], 3
([1, 2], 3) == foo()  # True
a, b = foo()  # works as expected: a = [1, 2] and b = 3
a, b = foo() if not condition else None, None  # now a = ([1, 2], 3) and b is None

我的问题是理解这里语法背后的基本原理。如果condition的计算结果为 false,为什么三元表达式的最后一部分,即else子句,会被计算出来呢?Python 是否将第二个None分配给b?这对我来说毫无意义,但我看不出还有什么 a( 没有引发 ValueError 来告诉我解包根本没有工作(如果我的语法以某种方式迫使 Python 将整个元组视为单个实体而不是解压缩它(和 b( 仍然为b赋值。显而易见的下一个测试:

a, b = foo() if not condition else None, 'test'  # Now a = ([1, 2], 3) and b = 'test'
a, b = (lambda x: [[1, 2], 3])('blah') if not condition else None, 'test'  # Same result with a lambda function.

因此,似乎正在评估 else 子句。为什么会这样?有没有一种优雅的重写方法,允许我在这样的三元表达式中调用函数,除了明显且可以说更笨拙的函数

if not condition:
a, b = foo()
else:
a, b = None, None

这只是优先级。Python 将其解析为:

a, b = (foo() if not condition else None), None

对于预期的结果,您需要在"无"两边添加括号:

a, b = foo() if not condition else (None, None)

这里发生的事情是,python 将你的三元表达式作为第一个要解压缩的项目,, None作为第二个项目。括号相同:

a, b = (foo() if not condition else None), None

这可以通过执行以下操作来缓解:

a, b = foo() if not condition else (None, None)

这将为您提供正确的结果:

>>> a, b = foo() if not condition else (None, None)
>>> a, b
([1, 2], 3)

最新更新