我刚刚了解到,新的walrus运算符(:=)不能用于设置实例属性,它应该是无效的语法(引发SyntaxError)。
为什么会这样?(您能提供一个指向提到这一点的官方文档的链接吗?)
我查看了佩普572,但是找不到是否/在哪里有文档记录。
Research
这个答案在没有解释或来源的情况下提到了这个限制:
不能在对象属性上使用walrus运算符
示例代码
class Foo:
def __init__(self):
self.foo: int = 0
def bar(self, value: int) -> None:
self.spam(self.foo := value) # Invalid syntax
def baz(self, value: int) -> None:
self.spam(temp := value)
self.foo = temp
def spam(self, value: int) -> None:
"""Do something with value."""试图导入Foo会导致SyntaxError
self.spam(self.foo := value)
^
SyntaxError: cannot use assignment expressions with attribute发布于 2020-09-24 22:41:40
PEP 572叙述了这项工作的目的(重点是地雷):
这是一种创建一种使用表示法在表达式中为变量分配的方法的建议。
self.foo不是变量,而是对象的属性。
语法和语义部分进一步指定了它:
NAME是一个标识符。
self.foo不是标识符,而是由.操作符分隔的两个标识符。
虽然我们经常类似地使用变量和属性,有时会草率地将self.foo称为变量,但它们并不相同。分配给self.foo实际上只是一个缩写
setattr(self, 'foo', temp)这就是允许您为属性定义getter和setter的内容。如果赋值表达式必须使用具有自定义设置器的属性,则它将使该表达式的规范和实现复杂化。
例如,如果setter转换正在赋值的值,则赋值表达式的值是原始值还是转换值?
另一方面,变量不能自定义。分配给变量总是具有相同的、简单的语义,表达式很容易计算出赋值的值。
类似地,您不能使用walrus运算符进行切片分配。这是无效的:
foo1[2:4] := foo2[1:3]发布于 2021-03-13 19:45:33
有趣的是,对walrussing object.attributes的禁止似乎只存在于Python的解析器中,该解析器将文本代码解析为抽象语法树(ast),然后进行编译和执行。如果您手动创建了一个ast语法树,其中self.foo取代了(var := temp)中的var,然后在compile或exec中创建了该树,那么它编译和执行就像您直觉地期望的那样。
所以很明显,它的基本功能是允许向object.attributes分配walrus,他们只是选择不让我们使用它,因为他们担心它会让人们编写混乱的代码或什么的。非常感谢..。
因此,无论如何,一个极端(一点也不推荐!)解决方案是你做一些预编译的自动手术,将你的object.attribute目标拼接到你的海象操作员中,然后它可能会像你预期的那样运行。(由于其他原因,我发现这是因为我已经做了一些简单的手术,用object.attributes代替了简单的变量,而且我很高兴发现海象任务仍然有效!)
https://stackoverflow.com/questions/64055314
复制相似问题