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

ご覧のとおり、の後にfor単純なステートメントまたは「スイート」、つまりインデントされたブロックを配置できます。ifステートメントは複合ステートメントであり、単純なステートメントではありません。

このプログラムを表現するには、最低2行です。

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

(もちろん、次のように1行だけで同等のプログラムを作成できます。

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するだけで、私が読んだときに文法があいまいになります。同じコードが2つ以上の異なる意味で解釈される可能性があり、どちらも反証できません。

基本的に、要求するのは解析エラーであるのは設計によるものです。形式文法を作り直すことで、例のコードを他の面白いものなしで機能させることができますが、あいまいさやその他の問題に注意を払う必要があります。

標準のAlgol-60言語を苦しめた文法の問題であるDanglingElseも参照してください。この種の問題を見つけるのは必ずしも簡単ではないので、動作する文法を変更することへの健全な恐れは良いことです。

于 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 ドキュメントには、文法がこれを許可しない理由に関する決定理由が記載されています。

スイートは、ヘッダーのコロンに続く、ヘッダーと同じ行のセミコロンで区切られた 1 つ以上の単純なステートメントである場合もあれば、後続の行の 1 つ以上のインデントされたステートメントである場合もあります。後者の形式のスイートのみが、ネストされた複合ステートメントを含むことができます。以下は違法です。主に、次のelse句がどのif句に属するかが明確ではないためです

if test1: if test2: print x

したがって、wberry回答では、Dangling Elseについては正しかったです。

于 2013-02-22T17:37:50.743 に答える