0

通過Python果殼中等價於一個try /除外/最後語句

一個try /除外/最後語句,如:

try: 
    ...guarded clause... 
except ...expression...: 
    ...exception handler code... 
finally: 
    ...clean-up code... 

相當於嵌套語句:

try: 
    try: 
     ...guarded clause... 
    except ...expression...: 
     ...exception handler code... 
finally: 
    ...clean-up code... 
  1. 爲什麼它相當於ŧ o嵌套形式?
  2. 它可以寫成相當於沒有finally的表單嗎?

    是否等同於

    try: 
        ...guarded clause... 
    except ...expression...: 
        ...exception handler code... 
        ...clean-up code... 
    ...clean-up code... 
    

感謝。

回答

1
  1. 因爲這就是它的定義。因爲這樣定義它是有用的和標準的,並且因爲沒有其他有用的方式來定義它。
  2. 是的,但不是你做到這一點。

    try: 
        do_stuff() 
    except OneProblem: 
        handle_it() 
    except DifferentProblem: 
        handle_that() 
    finally: 
        cleanup() 
    

    相當於

    try: 
        try: 
         do_stuff() 
        except OneProblem: 
         handle_it() 
        except DifferentProblem: 
         handle_that() 
    except: 
        # Clean up if an unhandled exception happened, then restore the exception. 
        cleanup() 
        raise 
    # Also clean up if we're not propagating an exception. 
    cleanup() 
    

在清理總是在發生,從來沒有發生兩次方面,雖然之類的異常鏈和回溯行爲可能不同。

+0

謝謝。第1部分和第2部分的答案也適用於Java的try ... catch..finally? – Tim

+0

如果最初的陳述只是嘗試...最後,即沒有趕上,可以在沒有嵌套的情況下簡化第2部分而不是最終給出的等價形式嗎?沒有最終的等效形式會是什麼樣子? – Tim

1

不,您的替代代碼不完全等同於try/except/finally版本。要理解爲什麼,請考慮如果在示例的...exception handler code...部分中觸發了第二個異常會發生什麼情況。

這裏有一個演示,顯示問題:

try: 
    print('in try')  # guarded code 
    1/0     # oops, a bug 
except ZeroDivisionError: 
    print('top of except') # exception handling code 
    name_does_not_exist  # oops, the exception handling code is buggy too 
    print('end of except') # this is a bad place for cleanup code 
finally: 
    print('in finally') # this is a much better place to do cleanup 

輸出:

in try 
top of except 
in finally 
Traceback (most recent call last): 

    File "<ipython-input-17-63590fc64963>", line 6, in <module> 
    name_does_not_exist  # oops, the exception handling code is buggy too 

NameError: name 'name_does_not_exist' is not defined 

注意,end of except消息永遠不會被印刷,因爲發生在上一行的NameError。如果行是重要的清理代碼,只有tryexcept的程序將無法運行它。但是,如果您將清理代碼放在finally區塊中,則無論代碼的任何其他部分出現任何異常,它都能保證運行。