以下に興味深いコードがあります。
def func1():
try:
return 1
finally:
return 2
def func2():
try:
raise ValueError()
except:
return 1
finally:
return 3
func1()
func2()
誰かがこれらの2つの関数を返す結果とその理由、つまり実行の順序を説明してください
Python ドキュメント
Finally節は、例外が発生したかどうかにかかわらず、常にtryステートメントを終了する前に実行されます。 try節で例外が発生し、except節で処理されなかった場合(またはexcept節またはelse節で発生した場合)、finally節が実行された後に例外が再発生します。 finally節は、tryステートメントの他の節がbreak、continue、またはreturnステートメントを介して残された場合も「途中で」実行されます。より複雑な例(同じtryステートメントにexcept節とfinally節があると、Python 2.5)のように機能します):
したがって、returnを使用してtry/exceptブロックが終了すると、戻り値が指定された値に設定され、最終的にブロックはalwaysを実行し、別のリターンを使用しながらリソースなどを解放するために使用する必要があります-元のリターンを上書きします。
特定のケースでは、func1()
は_2
_を返し、func2()
は_3
_を返します。これらはfinallyブロックで返される値であるためです。
常にfinally
ブロックに移動するため、return
およびtry
のexcept
は無視されます。 return
とtry
の上にexcept
がある場合、その値を返します。
def func1():
try:
return 1 # ignoring the return
finally:
return 2 # returns this return
def func2():
try:
raise ValueError()
except:
# is going to this exception block, but ignores the return because it needs to go to the finally
return 1
finally:
return 3
def func3():
return 0 # finds a return here, before the try except and finally block, so it will use this return
try:
raise ValueError()
except:
return 1
finally:
return 3
func1() # returns 2
func2() # returns 3
func3() # returns 0
事前にprint
ステートメントを置くと、本当に役立ちます。
def func1():
try:
print 'try statement in func1. after this return 1'
return 1
finally:
print 'after the try statement in func1, return 2'
return 2
def func2():
try:
print 'raise a value error'
raise ValueError()
except:
print 'an error has been raised! return 1!'
return 1
finally:
print 'okay after all that let\'s return 3'
return 3
print func1()
print func2()
これは返します:
try statement in func1. after this return 1
after the try statement in func1, return 2
2
raise a value error
an error has been raised! return 1!
okay after all that let's return 3
3
pythonは、両方の関数でreturn 1
に到達したかどうかに関係なく、常に最後に返されるものを返します。
finally
ブロックはalways runであるため、関数で最後に返されるのは、finallyブロックで返されるものです。 func1
では2です。func2
では3です。
func1()
は2を返します。func2()
は3を返します。
finally
ブロックは、例外に関係なく最終的に実行されます。
デバッガを使用して実行順序を確認できます。たとえば、 スクリーンキャスト を参照してください。