首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我不能指定一个命名表达式(LHS海象运算符)?

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

Stack Overflow用户
提问于 2020-11-25 13:47:16
回答 3查看 593关注 0票数 0

分配给表达式(相对于名称)在Python中很常见。例如,这是非常有效的语法:

代码语言:javascript
复制
my.object["with_some"].very_long["expression"] = func(my.object["with_some"].very_long["expression"], my.object["with_some"].very_long["expression"])

但是,如果我试图使用walrus运算符来缩短它,我会让LHS成为一个命名表达式,例如

代码语言:javascript
复制
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)

Python引发一个SyntaxError:

SyntaxError:不能分配给命名表达式

类似地,for x[0] in range(5)是有效的语法(只是非常混乱),而for (a:=x[0]) in range(5)又是一个SyntaxError: cannot assign to named expression

为什么我不能分配给一个命名的表达式?这是通过设计还是通过实现?

佩普572提到了不能使用walrus运算符的一些情况,但除了一种情况外,其余都是关于无括号表达式的语法,最后一种是关于f-字符串的。与这个答案 ((self.x := ...))中指出的情况不同,在我的示例中,walrus运算符中的赋值目标是一个简单的名称/标识符,而不是表达式。语言参考也不清楚为什么不允许这样做。在编写本报告时,搜索错误信息产生了三个结果:一个关于理解限制的问题,一个堆栈溢出聊天消息等待数百个热门网络问题 (没有发生)和第三方Python解析器中的一个问题;没有人帮助我。

我不能分配给命名表达式的原因是什么?这是一个在某个地方被记录或定义的设计规则,还是一个实现限制?据我所见,它不会导致任何歧义,而且我的用例应该是有效的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-11-25 14:31:32

代码语言:javascript
复制
my.object["with_some"].very_long["expression"] = \
  func(my.object["with_some"].very_long["expression"],
       my.object["with_some"].very_long["expression"])`

是句法上的糖

代码语言:javascript
复制
my.object["with_some"].very_long.__setitem__(
    "expression",
    func(my.object["with_some"].very_long["expression"], 
         my.object["with_some"].very_long["expression"]))

所以它不像你想的那样对称。原始长表达式的值(而不是表达式本身)作为两个参数传递给func,而原始表达式本身只是赋值的目标。

但是,你可以写

代码语言:javascript
复制
x["expression"] = func(
    (x:=my.object["with_some"].very_long)["expression"],
     x["expression"])

在将x分配给desugared版本的一个公共表达式的值时,my.object["with_some"].very_long

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

假设我适当地定义了A,下面是我用来验证上面是否应该工作的测试。

代码语言:javascript
复制
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的定义所期望的一样。

票数 1
EN

Stack Overflow用户

发布于 2020-11-25 13:56:39

海象运算符只将其赋值为副作用-它的值不是左手边变量,而是其右手边表达式的结果。

所以命名表达式的值

代码语言:javascript
复制
(x:=my.object["with_some"].very_long["expression"])

是海象运算符(:=)右侧的结果,即表达式的结果。

代码语言:javascript
复制
my.object["with_some"].very_long["expression"]

让我们表示为result,所以您的命令

代码语言:javascript
复制
(x:=my.object["with_some"].very_long["expression"]) = func(x, x)

是相同的

代码语言:javascript
复制
result = func(x, x)

现在,result是一个,而不是变量名。也许是None,也许是一个数字,可能是一个特定的列表或者其他什么东西,但是在赋值运算符的左边是不允许的。

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

票数 1
EN

Stack Overflow用户

发布于 2020-11-25 14:58:46

比较:

代码语言:javascript
复制
my.object["with_some"].very_long["expression"] = func(7, 7)      # OK

使用

代码语言:javascript
复制
7 = func(7, 7)                                                   # error

解释如下:

  1. 在你的第一个表情里 My.object“with_some”.very_long“表达式=\\my.object”with_some“.very_long”表达式) 您希望更改对象的属性的值(基于其当前属性的值),即执行以下操作 My.object“with_some”.very_long“表达式”= func(7,7)
  2. 在你的第二个表达式中 (x:=my.object"with_some".very_long"expression") = func(x,x) 赋值操作符(=)的左边不是对象的属性,而是它的值。 7=职能c(7,7)

来自PEP 572 -赋值表达式,摘要

这是一项关于创建一种分配给表达式中的变量的方法的建议.

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65005973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档