2012-10-17 46 views
4

我一直在嘗試一個簡單的執行轉換,如:爲什麼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 

我不看到這裏的任何含糊之處。有沒有特別的原因爲什麼會失敗?

+0

我可以問你爲什麼把它作爲一個班輪嗎?在我看來,這會讓閱讀變得更加困難,而不會有意義地改變代碼。 –

+0

@davemankoff當我意識到時,我只是在玩。我不確定我是否會使用它。它雖然在我看來並不醜陋,但.. – none

+0

同意,它不_that_醜陋,但我不會說它幫助代碼。玩它並學習語言如何工作肯定是件好事。我只是想警告你爲了一線球員而做單線球員。和其他人一樣,這不是一個非常好的習慣。 –

回答

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外面?是否在if之外呼叫foo?我認爲這表明我們真的不要想讓正式語法允許內聯複合語句。簡單地加入suite: compound_stmt會使語法在我閱讀時不明確,其中相同的代碼可以被解釋爲具有兩種或更多種不同的含義,這兩種含義都不可證僞。

基本上,它是由設計,你問的是一個解析錯誤。重寫正式的語法可以讓你的例子中的代碼在沒有其他有趣的東西的情況下工作,但它需要仔細注意模糊和其他問題。

另請參閱Dangling Else,這是一種語言問題,折磨了標準的Algol-60語言。找到這些問題並不總是容易的,因此,改變正常語法的健康恐懼是件好事。

+1

你用'try'奇怪的東西是什麼意思? – none

+0

用'try'「奇怪」的例子編輯回答。 – wberry

+0

儘管我覺得我仍然可以在很多沒有第二條語句的情況下使用它,但我想你的答案是懸掛在其他語句中。 – none

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 
+0

只是一個簡短的說明,我不得不留下一個空白的行這樣的工作,有趣的一種.. – none

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

我仍然沒有看到爲什麼這是實施它的方式的原因。順便說一句,我不只是打印甚至數字,這只是爲了演示.. – none

+1

@gokcehan我猜這樣蟒蛇可以保留它的縮進 – jamylak

+0

@gokcehan:我明白這只是一個例子。但jamylak可能是正確的,允許在一行中的任意數量的控制語句不會增加可讀性並且破壞基於縮進的語法的目的。 –

1

你可以試試這個:

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

我希望你沒有使用'x'作爲循環變量。 –

+0

哦,謝謝!爲了獲得更好的可讀性:'對於y in(x對於xrange中的x(10),如果x%2 == 0):print y' – swietyy

+0

我並不需要打印偶數的數字。這只是一個例子.. – none

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 
+0

我真的不需要打印偶數,反正它是微不足道的。 – none

1

Python文檔有關compound statements狀態的原因決定爲什麼沒有語法禁止這種

一間套房可以是一個或 同一行頭更分號分隔簡單的語句,下面的標頭的冒號,或者它可以是後續行中的一個或多個縮進語句。只有 套件的後一種形式可以包含嵌套的複合語句;該 以下是非法的,主要是因爲它不會清楚這是否 子句以下else子句將屬於

if test1: if test2: print x 

所以wberryanswer這是正確的關於Dangling Else

+0

不錯,謝謝你挖掘它,你有我的+1。 – none