为什么一行上的嵌套控制语句在python中失败?

时间:2012-10-17 18:42:36

标签: python

我一直试图转换一个简单的执行,例如:

for x in xrange(10):
    if x % 2 == 0:
        print x, 'is even'

到单线版:

for x in xrange(10): if x % 2 == 0: print x, 'is even'

给了我:

  File "foo.py", line 1
    for x in xrange(10): if x % 2 == 0: print x, 'is even'
                      ^
SyntaxError: invalid syntax

我在这里看不出任何含糊之处。是否有特殊原因导致失败?

6 个答案:

答案 0 :(得分:5)

the grammar根本不允许这样做。相关的作品是:

for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

正如您所看到的,在for之后,您可以放置​​一个简单的语句或“套件”,即缩进的块。 if语句是复合语句,而不是简单语句。

表示此计划的最低限度为两行:

for x in xrange(10):
    if x % 2 == 0: print x, 'is even'

(当然,您可以编写只占一行的等效程序,例如

for x in xrange(0, 10, 2): print x, "is even"

或针对此问题发布的任何其他单行人员。)

答案 1 :(得分:3)

来自formal grammar for 2.7

compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated

if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]

suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | exec_stmt | assert_stmt)

如果suite允许compound_stmt,那么您的建议将被接受。但这也可以允许这样的事情:

if True: try:
  # do something
except:
  # handle
foo()

except在封闭的if之外吗?是封闭foo之外的if来电吗?我认为这表明我们确实希望正式语法允许内联复合语句。简单地添加suite: compound_stmt会使语法在我阅读时模糊不清,其中相同的代码可以用两种或更多种不同的含义来解释,既不可以解决。

基本上,根据设计,您要求的是解析错误。重写正式语法可以让你的例子中的代码在没有其他有趣的东西的情况下工作,但是需要注意模糊和其他问题。

另见Dangling Else,这是一个困扰标准Algol-60语言的语法问题。找到这些问题并不总是那么容易,所以改变工作语法的健康恐惧是一件好事。

答案 2 :(得分:1)

尝试类似:

In [14]: from __future__ import print_function

In [17]: for x in xrange(10): print (x,'is even') if x%2==0 else None
   ....: 
0 is even
2 is even
4 is even
6 is even
8 is even

答案 3 :(得分:1)

你可以试试这个:

for y in (x for x in xrange(10) if x % 2 == 0): print y

答案 4 :(得分:1)

如果你想要类似的东西,请使用列表理解:

print '\n'.join('{0} is even'.format(x) for x in xrange(10) if x % 2 == 0)

打印:

0 is even
2 is even
4 is even
6 is even
8 is even

答案 5 :(得分:1)

关于compound statements的Python文档声明 em>语法不允许这个:

  

套件可以是一个或多个以分号分隔的简单语句   与标题相同的行,在标题的冒号后面,或者它可以   在后续行上是一个或多个缩进语句。只有   后一种形式的套件可以包含嵌套的复合语句;该   以下是非法的,主要是因为它不清楚如果   条款以下其他条款属于

if test1: if test2: print x

所以在wberryanswerDangling Else是正确的。{{3}}。