2011-11-28 32 views
36

下面的代碼引發一個語法錯誤:爲什麼在Python的`finally`子句中不允許'繼續'?

>>> for i in range(10): 
...  print i 
...  try: 
...  pass 
...  finally: 
...  continue 
...  print i 
... 
    File "<stdin>", line 6 
SyntaxError: 'continue' not supported inside 'finally' clause 

爲什麼不允許一個finally條款內continue聲明?

P.S.另一方面,這個其他代碼沒有問題:

>>> for i in range(10): 
...  print i 
...  try: 
...  pass 
...  finally: 
...  break 
... 
0 

如果它很重要,我使用Python 2.6.6。

+2

看起來只是純粹的懶惰? http://www.gossamer-threads.com/lists/python/dev/484210 –

+0

@Mike Christensen:我也發現這個線程,但是文檔說「繼續可能只會出現在語法上嵌套在for或while循環中,但不會嵌套在函數或類定義**或該循環中的finally子句**中。那麼這是懶惰還是故意的,後來需要改變? ...像Python中的很多東西... – ElenaT

+0

你讀過整個線程嗎? - 有一些有趣的信息可以說明它會在finally塊中「繼續」,以及可能出現的各種問題。值得閱讀。 –

回答

24

在finally子句中使用繼續是禁止的,因爲它的解釋會有問題。如果finally子句由於異常而被執行,你會怎麼做?

for i in range(10): 
    print i 
    try: 
     raise RuntimeError 
    finally: 
     continue  # if the loop continues, what would happen to the exception? 
    print i 

我們有可能做出這個代碼應該做什麼的決定,或許吞下異常;但良好的語言設計表明否則。如果代碼使讀者感到困惑,或者如果有更明確的方式來表達預期的邏輯(可能與try: ... except Exception: pass; continue),那麼將其作爲SyntaxError有一些優勢。

有趣的是,你可以把一個一個最終子句中,它會吞下所有的異常,包括一個KeyboardInterruptSystemExit的MemoryError。這可能不是一個好主意;-)

+4

我同意。如果異常中斷了你的程序,那麼finally子句的用法通常是用來結束鬆散的結束。對於「最後繼續」(在英語中也是無意義的),如果存在影響循環條件本身的問題,將會有重複異常的風險,直到循環終止,甚至無限重複。 – paislee

+2

在finally塊中繼續可以按照與返回或加註相同的方式進行處理。在這個例子中,異常將被吞下並且循環將繼續。 –

+2

我認爲人們忘記了'finally'塊中的代碼總是被執行。 – jathanism

6

finally子句中的Python語言參考forbids the use of continue。我不完全確定爲什麼。也許是因爲在try子句中的continue確保finally被執行,並且在finally子句中決定什麼continue應該有點含糊不清。

編輯:@Mike Christensen對這個問題的評論指出了一個線程,這個構造的含糊性由Python核心開發人員討論。另外,在使用Python九年多的時間裏,我從來不想這樣做,所以開發人員不會花費太多時間,這可能是一種相對不常見的情況。

+0

似乎是一個很好的解釋給我。 'finally'和'continue'的組合肯定是值得重構的東西。 – jsalonen

+2

在這些情況下,有時候最好不要讓開發人員去做某些事情 - 否則你必須規範,解決和解決允許這種事情的決定產生的任何古怪。 –

3

我認爲這樣做的原因其實很簡單。 finally關鍵字之後的continue語句每次都執行。這是最後聲明的本質。你的代碼是否拋出異常是無關緊要的。最後會被執行。

因此,你的代碼...

for i in range(10): 
    print i 
    try: 
     pass 
    finally: 
     continue 
    print i # this (and anything else below the continue) won't ever be executed! 

相當於該代碼...

for i in range(10: 
    print i 
    try: 
     pass 
    finally: 
     pass 

這是更清潔和更簡潔。 Python不允許在finally塊中繼續,因爲continue之後的所有代碼都不會執行。 (稀疏比密集好。)

2

我沒有看到它在另一個迴應中提到,但我想你可能想在這種情況下,是什麼try..else

for i in range(10): 
    print i 
    try: 
     #pass <= I commented this out! 
     do_something_that_might_fail(i) 
    except SomeException: 
     pass 
    else: 
     continue 
    print i 

else塊如果沒有異常,才能執行。所以,這是什麼意思是:

  1. 我們print i
  2. 我們trydo_something_that_might_fail(i)
  3. 如果它拋出SomeException,砸鍋和print i再次
  4. 否則,我們continue(和i從不打印)
2

獲得例外的可能性,然後只是吞下,因爲喲我使用continue是一個有力的論據,但是當您使用breakreturn代替時,也會吞噬異常。

例如,這個工作和異常吞嚥:

for i in range(10): 
    print i 
    try: 
     raise Exception 
    finally: 
     break 
    print i  # not gonna happen 

這再次,沒有錯誤的工作(在功能時)和異常吞嚥太:

for i in range(10): 
    print i 
    try: 
     raise Exception 
    finally: 
     return 
    print i  # not gonna happen 

那麼,爲什麼breakreturn被允許在finally塊中,有無可能引發的錯誤,但是continue不是?

您也可以考慮在發行的以下幾個因素的結合:

  • finally總是執行;
  • continue「中止」當前迭代。

這將意味着每個循環中,因爲finally始終執行,你將永遠有一個continue女巫基本上 說:「放棄當前迭代」,「中止當前迭代」,「中止當前迭代」 ..女巫沒有任何意義。但是使用breakreturn也沒有意義。當前的迭代也會中止,唯一的差異是 ,您現在只需要一次迭代即可完成。

所以問題「爲什麼continue不允許在finally?」也可以被問爲「爲什麼允許breakreturn?」。

也許是因爲它在這一點上有意義嗎? 這是開發者的決定,現在它是這樣嗎?當然,這也可能是實現者的懶惰,但是誰知道,也許他們有一些想法,或許在另一個版本的Python中,它會讓更多的其他方式感覺到它呢?

想法是,這裏的例子只是極端的。你不只是寫這樣的代碼,是嗎?無論如何,在finally塊中肯定會有一些 邏輯來說明何時break/return/continue,而不僅僅是這樣。因此,應該允許在finally之內的恕我直言continue,因爲如果這是我所需要的,我將不用訴諸於代碼解決方法來解決此限制(例如,在Python的哲學中「我們都是同意這裏的成年人「)。

+1

我對這個討論有點遲,但'finally'子句中的'continue'語句並不一定意味着每一次迭代都會被中止,因爲你可以將'continue'語句包裝在一個條件語句中。 (這仍然是一個SyntaxError。) – Fraxtil

相關問題