Python 为什么我不能指定一个命名表达式(LHS walrus运算符)?

Python 为什么我不能指定一个命名表达式(LHS walrus运算符)?,python,syntax-error,python-3.8,walrus-operator,Python,Syntax Error,Python 3.8,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"])

赋值给表达式(而不是名称)在Python中很常见。例如,这是非常有效的语法:

my.object["with_some"].very_long["expression"] = func(my.object["with_some"].very_long["expression"], my.object["with_some"].very_long["expression"])
但是,如果我尝试使用walrus操作符通过使LHS成为一个命名表达式来缩短它,例如

(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
Python引发了一个语法错误:

SyntaxError:无法分配给命名表达式

(x:=my.object["with_some"].very_long["expression"])
my.object["with_some"].very_long["expression"]
my.object["with_some"].very_long["expression"] = \
    func(my.object["with_some"].very_long["expression"],               
          my.object["with_some"].very_long["expression"])
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
类似地,范围(5)中x[0]的
是有效语法(非常容易混淆),而范围(5)
中(a:=x[0])的
又是
语法错误:无法分配给命名表达式

为什么我不能指定一个命名表达式?这是设计还是实施

提到了一些不能使用walrus运算符的情况,但除了一个以外,其他所有情况都与未加密表达式的语法有关,最后一个是关于f字符串的。与(
(self.x:=…)
中指出的情况不同,在我的例子中,walrus操作符中的赋值目标是一个简单的名称/标识符,而不是表达式。这两个方面都不清楚为什么不允许这样做。在撰写本文时,今天正好产生了三个结果:一,a(没有发生),和;谁也帮不了我


我无法指定给命名表达式的原因是什么?这是某个地方记录或定义的设计规则,还是实施限制?就我所见,它不会导致任何歧义,而且我的用例似乎应该是有效的。

walrus操作符只作为副作用进行赋值-它的值不是左侧变量,而是右侧表达式的结果

因此,命名表达式的值

(x:=my.object["with_some"].very_long["expression"])
my.object["with_some"].very_long["expression"]
my.object["with_some"].very_long["expression"] = \
    func(my.object["with_some"].very_long["expression"],               
          my.object["with_some"].very_long["expression"])
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
是walrus运算符右侧的结果(
:=
),即。E表达式的结果

(x:=my.object["with_some"].very_long["expression"])
my.object["with_some"].very_long["expression"]
my.object["with_some"].very_long["expression"] = \
    func(my.object["with_some"].very_long["expression"],               
          my.object["with_some"].very_long["expression"])
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
让我们将其表示为
结果
,因此您的命令

(x:=my.object["with_some"].very_long["expression"]) = func(x, x)

result = func(x, x)
现在,
结果
是一个,而不是变量名。可能是
None
,可能是一个数字,可能是一个特定的列表或其他内容,但不允许在赋值运算符的左侧


因此,赋值给命名表达式(至少在大多数情况下)是没有意义的,因此是不允许的。

walrus操作符只作为副作用赋值-它的值不是左侧变量,而是右侧表达式的结果

my.object["with_some"].very_long["expression"] = \
  func(my.object["with_some"].very_long["expression"],
       my.object["with_some"].very_long["expression"])`
因此,命名表达式的值

(x:=my.object["with_some"].very_long["expression"])
my.object["with_some"].very_long["expression"]
my.object["with_some"].very_long["expression"] = \
    func(my.object["with_some"].very_long["expression"],               
          my.object["with_some"].very_long["expression"])
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
是walrus运算符右侧的结果(
:=
),即。E表达式的结果

(x:=my.object["with_some"].very_long["expression"])
my.object["with_some"].very_long["expression"]
my.object["with_some"].very_long["expression"] = \
    func(my.object["with_some"].very_long["expression"],               
          my.object["with_some"].very_long["expression"])
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)
让我们将其表示为
结果
,因此您的命令

(x:=my.object["with_some"].very_long["expression"]) = func(x, x)

result = func(x, x)
现在,
结果
是一个,而不是变量名。可能是
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"]))
所以它不像你想象的那样对称。原始长表达式的值(而不是表达式本身)作为两个参数传递给
func
,而原始表达式本身只是赋值的一种目标

然而,你可以写

x["expression"] = func(
    (x:=my.object["with_some"].very_long)["expression"],
     x["expression"])
x
被分配一个通用表达式的值给被删除的版本时,
my.object[“with_some”]。非常长

赋值表达式必须位于赋值的右侧,因为它在左侧之前求值。此外,它必须是使用
:=
的第一个参数,因为函数参数保证从左到右求值


假设我正确定义了
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.__setitem__(
    "expression",
    func(my.object["with_some"].very_long["expression"], 
         my.object["with_some"].very_long["expression"]))
所以它不像你想象的那样对称。原始长表达式的值(而不是表达式本身)作为两个参数传递给
func
,而原始表达式本身只是赋值的一种目标

然而,你可以写

x["expression"] = func(
    (x:=my.object["with_some"].very_long)["expression"],
     x["expression"])
x
被分配一个通用表达式的值给被删除的版本时,
my.object[“with_some”]。非常长

赋值表达式必须位于赋值的右侧,因为它在左侧之前求值。此外,它必须是使用
:=
的第一个参数,因为函数参数保证从左到右求值


假设我正确定义了
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


解释如下:

  • 在你的第一个表情中

    (x:=my.object["with_some"].very_long["expression"])
    
    my.object["with_some"].very_long["expression"]
    
    my.object["with_some"].very_long["expression"] = \
        func(my.object["with_some"].very_long["expression"],               
              my.object["with_some"].very_long["expression"])
    
    (x:=my.object["with_some"].very_long["expression"]) = func(x, x)
    
    您希望更改对象的属性的值(基于其当前属性的值),即按以下方式执行操作:

    my.object["with_some"].very_long["expression"] = func(7, 7)
    
    7 = func(7, 7)
    
  • 在你的第二个表情中

    (x:=my.object["with_some"].very_long["expression"])
    
    my.object["with_some"].very_long["expression"]
    
    my.object["with_some"].very_long["expression"] = \
        func(my.object["with_some"].very_long["expression"],               
              my.object["with_some"].very_long["expression"])
    
    (x:=my.object["with_some"].very_long["expression"]) = func(x, x)
    
    赋值运算符
    (=)
    的左侧不是对象的属性,而是对象的值。因此,您尝试将某个值赋值,即按

    my.object["with_some"].very_long["expression"] = func(7, 7)
    
    7 = func(7, 7)
    
  • 发件人:

    这是一个建议,用于创建一种在表达式中为变量赋值的方法

    没有提到在分配的LHS中使用它。

    比较:

    my.object["with_some"].very_long["expression"] = func(7, 7)      # OK
    


    解释如下:

  • 在你的第一个表情中

    (x:=my.object["with_some"].very_long["expression"])
    
    my.object["with_some"].very_long["expression"]
    
    my.object["with_some"].very_long["expression"] = \
        func(my.object["with_some"].very_long["expression"],               
              my.object["with_some"].very_long["expression"])
    
    (x:=my.object["with_some"].very_long["expression"]) = func(x, x)
    
    您希望更改对象的属性的值(基于其当前属性的值),即执行以下操作