for循环名称列表表达式是否合法?
问题描述:
在CPython 2.7.10和3.4.3以及PyPy 2.6.0(Python 2.7.9)中,为for循环中的名称列表使用表达式(或其中的一些子集)显然是合法的。下面是一个典型的循环:for循环名称列表表达式是否合法?
>>> for a in [1]: pass
...
>>> a
1
但你也可以使用属性的对象:
>>> class Obj(object): pass
...
>>> obj = Obj()
>>> for obj.b in [1]: pass
...
>>> obj.b
1
你甚至可以从表达式中使用属性:
>>> for Obj().c in [1]: pass
...
但并不是所有的表达式似乎工作:
>>> for (True and obj.d) in [1]: pass
...
File "<stdin>", line 1
SyntaxError: can't assign to operator
但是只要属性在外面,他们就会这样做?
>>> for (True and obj).e in [1]: pass
...
>>> obj.e
1
或者什么是可分配的?
>>> for {}['f'] in [1]: pass
...
我很惊讶这些都是Python中的合法语法。我希望只有名字被允许。这些甚至应该工作吗?这是一个疏忽吗?这是Pyyy恰好也实现了CPython的实现细节吗?
答
这些甚至应该工作吗?
是
这是一个疏忽?
没有
这是CPython中的实现细节,PyPy恰好也 实现?
没有
如果你能分配给它,你可以使用它作为在for循环中游离不定。
对于这样的问题,这是值得直行到grammar:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
一个target_list
只是一堆的target
:
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" target_list ")"
| "[" [target_list] "]"
| attributeref
| subscription
| slicing
| "*" target
如果你在那仔细观察,你会看到你给出的例子都不是反例。请注意,解析器中的错误并非闻所未闻(even I found one once),所以如果您发现合法的语法异常,那么通过提交一张票 - 这些错误往往会很快得到修复。
你给我的最有趣的是一对和(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()))])"
注:(True and obj).d
是在语法的attributeref
。
答
如documented,在for
语法“可变”可以是任何target_list
,其中,因为also documented指任何可以在一个赋值语句的左手侧。你显然不能使用像(True and obj.d)
这样的东西,因为没有办法给它赋值。
是((True and obj).e =“hello”'有效的语法? –
......回答我自己的问题:不,事实并非如此。 –
在dictionary.items()中为'k,v做些什么? –