for循环名称列表表达式合法吗? [英] Are for-loop name list expressions legal?

查看:111
本文介绍了for循环名称列表表达式合法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In CPython 2.7.10 and 3.4.3, and PyPy 2.6.0 (Python 2.7.9), it is apparently legal to use expressions (or some subset of them) for the name list in a for-loop. Here's a typical for-loop:

>>> for a in [1]: pass
...
>>> a
1

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

But you can also use attributes from objects:

>>> class Obj(object): pass
...
>>> obj = Obj()
>>> for obj.b in [1]: pass
...
>>> obj.b
1

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

And you can even use attributes from expressions:

>>> for Obj().c in [1]: pass
...

但并非所有表达式都起作用:

But not all expressions appear to work:

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

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

But they do so long as the attribute is on the outside?

>>> for (True and obj).e in [1]: pass
...
>>> obj.e
1

还是可以分配的东西?

>>> for {}['f'] in [1]: pass
...

我很惊讶所有这些都是Python中的合法语法.我希望只允许使用名字.这些甚至应该起作用吗?这是疏忽吗?这是PyPy恰好也实现的CPython的实现细节吗?

I'm surprised any of these are legal syntax in Python. I expected only names to be allowed. Are these even supposed to work? Is this an oversight? Is this an implementation detail of CPython that PyPy happens to also implement?

推荐答案

这些甚至应该起作用吗?

Are these even supposed to work?

这是疏忽吗?

Is this an oversight?

PyPy也是CPython的实现细节吗? 实施?

Is this an implementation detail of CPython that PyPy happens to also implement?

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

If you can assign to it, you can use it as the free variable in the for loop.

对于这样的问题,值得直接参考语法:

For questions like this, it's worth going straight to the 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

如果仔细观察,您会发现您给出的所有工作示例都不是反例.请注意,解析器中的错误并非闻所未闻(一次发现),因此,如果您发现合法的语法异常,则可以通过提交票证-这些往往会很快得到解决.

If you look at that closely, you'll see that none of the working examples you've given is a counter-example. Mind you, bugs in the parser are not unheard of (even I found one once), so if you find a legitimate syntax anomaly then by means submit a ticket - these tend to get fixed quickly.

您给出的最有趣的对是(True and obj.d)(True and obj).d,它们在逻辑上似乎相同,但解析方式不同:

The most interesting pair you gave is (True and obj.d) and (True and obj).d, which seem to be the same logically but are parsed differently:

>>> 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 .

这篇关于for循环名称列表表达式合法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆