显然 (至少对我来说是令人惊讶的),这在 Python 3.6+ 中是一个完全有效的表达式。
x: 10
这到底是怎么回事? 我检查了一下,用 ast
模块,并得到了以下内容。
[ins] In [1]: ast.parse('x: 10').body
Out[1]: [<_ast.AnnAssign at 0x110ff5be0>]
好吧,所以这是一个注释的任务。我查了一下 语法参考 并看到它对应的是这个规则。
annassign: ':' test ['=' test]
这对我来说没有太大意义 如果它是一个注释的 任务那么,为什么表达式的赋值部分是可选的?如果表达式的赋值部分不存在,这可能意味着什么?这不是很奇怪吗?
在这里,我想说的是,如果表达式中的赋值部分不存在,那么,为什么表达式的赋值部分是可选的呢?annasign
节点只在一条规则中被引用。
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
在该层的其他可能的投影中,都需要某种赋值表达式(augassign
是一个象征性的东西,如 +=
). 那么,为什么它是可选的 annassign
?
我想,这可能是一个裸名表达式的注释版本(即只有 x
),但这真的很让人困惑。我对静态类型检查器不是很熟悉,但他们能不能利用这样的注释?
更有可能是有意为之,但这看起来有点像一个bug。这有点问题,因为有可能写出这样语法上有效但完全无意义的代码。
a = 1
b = 2
c: 3 # see what I did there? oops!
d = 4
我最近在自己的代码中也犯了一个类似的错误 当我把一个... ... dict
表示法变成独立的变量,当我的测试管道在Python 3.5环境中运行并产生一个 SyntaxError
.
总之,我主要是对其意图感到好奇,但如果发现我发现了一个实际的语法错误,也会非常兴奋。
由于解析器的原因,它被归为注解赋值。如果有单独的 annotation
和 annassign
规则,Python的LL(1)解析器在看到冒号时就无法判断它应该解析的是哪一个。