for循环名称列表表达式是否合法?

use*_*450 4 python language-lawyer

在CPython 2.7.10和3.4.3以及PyPy 2.6.0(Python 2.7.9)中,在for循环中使用表达式(或它们的某些子集)作为名称列表显然是合法的.这是一个典型的for循环:

>>> for a in [1]: pass
...
>>> a
1
Run Code Online (Sandbox Code Playgroud)

但您也可以使用对象中的属性:

>>> class Obj(object): pass
...
>>> obj = Obj()
>>> for obj.b in [1]: pass
...
>>> obj.b
1
Run Code Online (Sandbox Code Playgroud)

你甚至可以使用表达式中的属性:

>>> for Obj().c in [1]: pass
...
Run Code Online (Sandbox Code Playgroud)

但并非所有表达式都可行:

>>> for (True and obj.d) in [1]: pass
...
  File "<stdin>", line 1
SyntaxError: can't assign to operator
Run Code Online (Sandbox Code Playgroud)

但只要属性在外面,他们就会这样做吗?

>>> for (True and obj).e in [1]: pass
...
>>> obj.e
1
Run Code Online (Sandbox Code Playgroud)

或者可以分配什么?

>>> for {}['f'] in [1]: pass
...
Run Code Online (Sandbox Code Playgroud)

我很惊讶这些都是Python中的合法语法.我希望只允许名字.这些甚至应该有效吗?这是疏忽吗?这是PyPy碰巧也实现的CPython的实现细节吗?

wim*_*wim 5

这些甚至应该有效吗?

这是疏忽吗?

没有

这是PyPy碰巧也实现的CPython的实现细节吗?

没有


如果可以为其分配,则可以将其用作for循环中的自由变量.

对于这样的问题,值得直接使用语法:

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]
Run Code Online (Sandbox Code Playgroud)

A target_list只是一堆target:

target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" target_list ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target
Run Code Online (Sandbox Code Playgroud)

如果你仔细研究一下,你会发现你给出的所有工作实例都不是反例.请注意,解析器中的错误并非闻所未闻(即使我发现了一次),所以如果您发现合法的语法异常,那么通过提交票证 - 这些往往会很快得到修复.

你给我的最有趣的是对(True and obj.d)(True and obj).d,这似乎是逻辑上是相同但分析不同:

>>> ast.dump(ast.parse('(True and obj.d)'), annotate_fields=False)
"Module([Expr(BoolOp(And(), [Name('True', Load()), Attribute(Name('obj', Load()), 'd', Load())]))])"
>>> ast.dump(ast.parse('(True and obj).d'), annotate_fields=False)
"Module([Expr(Attribute(BoolOp(And(), [Name('True', Load()), Name('obj', Load())]), 'd', Load()))])"
Run Code Online (Sandbox Code Playgroud)

注意: (True and obj).dattributeref语法中的一个.