为什么我不能分配给命名表达式(LHS 海象运算符)?
Why can I not assign to a named expression (LHS walrus operator)?
在 Python 中,给表达式赋值(而不是名称)很常见。例如,这是完全有效的语法:
my.object["with_some"].very_long["expression"] = func(my.object["with_some"].very_long["expression"], my.object["with_some"].very_long["expression"])
但是,如果我尝试使用海象运算符通过将 LHS 设为命名表达式来缩短它,例如
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
Python 引发 SyntaxError:
SyntaxError: cannot assign to named expression
同样,for x[0] in range(5)
是有效语法(只是非常混乱),而 for (a:=x[0]) in range(5)
又是 SyntaxError: cannot assign to named expression
.
为什么我不能给命名表达式赋值?这是设计还是实现?
PEP 572 mentions some cases where the walrus operator cannot be used, but all but one are about the syntax of unparenthesised expressions and the final one is about f-strings. Unlike the situation pointed out in ((self.x := ...)
), the assignment target within the walrus operator in my case is a simple name/identifier, not an expression. It's not clear from the language reference either why this is not allowed. Googling the error message today yields exactly three results at the time of writing: One issue about limitations in comprehensions, a Stack Overflow chat message expecting hundreds of Hot Network Questions (which didn't happen), and an issue in a 3rd-party Python parser; none帮帮我。
我无法分配给命名表达式的原因是什么?这是在某处记录或定义的设计规则,还是实施限制?据我所知,它不会导致任何歧义,而且我的用例似乎应该是有效的。
海象运算符仅作为副作用赋值 - 它的值不是左侧变量,而是它的右侧表达式。
所以命名表达式的值
(x:=my.object["with_some"].very_long["expression"])
是海象算子右边的结果(:=
),i。 e.表达式的结果
my.object["with_some"].very_long["expression"]
让我们表示为 result
,所以您的命令
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
与
相同
result = func(x, x)
现在,result
是一个 值 ,而不是 变量名 。也许 None
,也许是一个数字,也许是一个特定的列表或其他东西,但是 不允许出现在赋值运算符的左侧。
因此,分配给命名表达式(至少在大多数情况下)是没有意义的,因此是不允许的。
my.object["with_some"].very_long["expression"] = \
func(my.object["with_some"].very_long["expression"],
my.object["with_some"].very_long["expression"])`
是
的语法糖
my.object["with_some"].very_long.__setitem__(
"expression",
func(my.object["with_some"].very_long["expression"],
my.object["with_some"].very_long["expression"]))
所以它并不像你想象的那样对称。原始长表达式的 value,而不是表达式本身,作为两个参数传递给 func
,原始表达式本身只是 种 赋值的目标。
你可以,但是,写
x["expression"] = func(
(x:=my.object["with_some"].very_long)["expression"],
x["expression"])
其中 x
被分配了一个通用表达式的值给脱糖版本,my.object["with_some"].very_long
。
赋值表达式必须在赋值的右侧,因为它是在左侧之前计算的。此外,它必须是使用 :=
的 第一个 参数,因为函数参数保证从左到右计算。
假设我适当地定义了 A
,这是我用来验证以上内容是否有效的测试。
class A:
def __init__(self, y):
self.b = dict(foo=y)
def func(x, y):
return x + y
a = A(A("bar"))
x["foo"] = func((x:=a.b["foo"].b)["foo"], x["foo"])
a.b["foo"].b["foo"]
的新值是 "barbar"
,正如 func
的定义所预期的那样。
比较:
my.object["with_some"].very_long["expression"] = func(7, 7) # OK
和
7 = func(7, 7) # error
解释:
在你的第一个表达式中
my.object["with_some"].very_long["expression"] = \
func(my.object["with_some"].very_long["expression"],
my.object["with_some"].very_long["expression"])
您想更改对象的 属性 的值(基于其当前属性的值),即做一些事情
my.object["with_some"].very_long["expression"] = func(7, 7)
在你的第二个表达式中
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
赋值运算符 (=)
的左侧不是您对象的属性,而是它的 值。 所以您尝试将某些东西赋值给 值,即做某事为
7 = func(7, 7)
来自PEP 572 - Assignment Expressions, Abstract:
This is a proposal for creating a way to assign to variables within an expression...
作业的LHS中没有提到使用它。
在 Python 中,给表达式赋值(而不是名称)很常见。例如,这是完全有效的语法:
my.object["with_some"].very_long["expression"] = func(my.object["with_some"].very_long["expression"], my.object["with_some"].very_long["expression"])
但是,如果我尝试使用海象运算符通过将 LHS 设为命名表达式来缩短它,例如
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
Python 引发 SyntaxError:
SyntaxError: cannot assign to named expression
同样,for x[0] in range(5)
是有效语法(只是非常混乱),而 for (a:=x[0]) in range(5)
又是 SyntaxError: cannot assign to named expression
.
为什么我不能给命名表达式赋值?这是设计还是实现?
PEP 572 mentions some cases where the walrus operator cannot be used, but all but one are about the syntax of unparenthesised expressions and the final one is about f-strings. Unlike the situation pointed out in (self.x := ...)
), the assignment target within the walrus operator in my case is a simple name/identifier, not an expression. It's not clear from the language reference either why this is not allowed. Googling the error message today yields exactly three results at the time of writing: One issue about limitations in comprehensions, a Stack Overflow chat message expecting hundreds of Hot Network Questions (which didn't happen), and an issue in a 3rd-party Python parser; none帮帮我。
我无法分配给命名表达式的原因是什么?这是在某处记录或定义的设计规则,还是实施限制?据我所知,它不会导致任何歧义,而且我的用例似乎应该是有效的。
海象运算符仅作为副作用赋值 - 它的值不是左侧变量,而是它的右侧表达式。
所以命名表达式的值
(x:=my.object["with_some"].very_long["expression"])
是海象算子右边的结果(:=
),i。 e.表达式的结果
my.object["with_some"].very_long["expression"]
让我们表示为 result
,所以您的命令
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
与
相同result = func(x, x)
现在,result
是一个 值 ,而不是 变量名 。也许 None
,也许是一个数字,也许是一个特定的列表或其他东西,但是 不允许出现在赋值运算符的左侧。
因此,分配给命名表达式(至少在大多数情况下)是没有意义的,因此是不允许的。
my.object["with_some"].very_long["expression"] = \
func(my.object["with_some"].very_long["expression"],
my.object["with_some"].very_long["expression"])`
是
的语法糖my.object["with_some"].very_long.__setitem__(
"expression",
func(my.object["with_some"].very_long["expression"],
my.object["with_some"].very_long["expression"]))
所以它并不像你想象的那样对称。原始长表达式的 value,而不是表达式本身,作为两个参数传递给 func
,原始表达式本身只是 种 赋值的目标。
你可以,但是,写
x["expression"] = func(
(x:=my.object["with_some"].very_long)["expression"],
x["expression"])
其中 x
被分配了一个通用表达式的值给脱糖版本,my.object["with_some"].very_long
。
赋值表达式必须在赋值的右侧,因为它是在左侧之前计算的。此外,它必须是使用 :=
的 第一个 参数,因为函数参数保证从左到右计算。
假设我适当地定义了 A
,这是我用来验证以上内容是否有效的测试。
class A:
def __init__(self, y):
self.b = dict(foo=y)
def func(x, y):
return x + y
a = A(A("bar"))
x["foo"] = func((x:=a.b["foo"].b)["foo"], x["foo"])
a.b["foo"].b["foo"]
的新值是 "barbar"
,正如 func
的定义所预期的那样。
比较:
my.object["with_some"].very_long["expression"] = func(7, 7) # OK
和
7 = func(7, 7) # error
解释:
在你的第一个表达式中
my.object["with_some"].very_long["expression"] = \ func(my.object["with_some"].very_long["expression"], my.object["with_some"].very_long["expression"])
您想更改对象的 属性 的值(基于其当前属性的值),即做一些事情
my.object["with_some"].very_long["expression"] = func(7, 7)
在你的第二个表达式中
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
赋值运算符
(=)
的左侧不是您对象的属性,而是它的 值。 所以您尝试将某些东西赋值给 值,即做某事为7 = func(7, 7)
来自PEP 572 - Assignment Expressions, Abstract:
This is a proposal for creating a way to assign to variables within an expression...
作业的LHS中没有提到使用它。