4

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

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

我在这里没有看到任何歧义。失败有什么特别的原因吗?

4

6 回答 6

5

语法根本不允许这样做。相关产品有:

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

如您所见,在 a 之后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"

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

于 2012-10-17T18:47:36.713 回答
3

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 语言的语法问题。发现这类问题并不总是那么容易,因此对改变有效语法的健康恐惧是一件好事。

于 2012-10-17T18:49:26.167 回答
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
于 2012-10-17T18:45:24.577 回答
1

你可以试试这个:

for y in (x for x in xrange(10) if x % 2 == 0): print y
于 2012-10-17T19:05:11.477 回答
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
于 2012-10-17T19:06:18.027 回答
1

关于复合语句的 Python 文档说明了为什么语法不允许这样做的决定原因

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

if test1: if test2: print x

所以在wberry回答中,关于 Dangling Else是正确的。

于 2013-02-22T17:37:50.743 回答