try
句内に return ステートメントがあります。
def f():
try:
return whatever()
finally:
pass # How do I get what `whatever()` returned in here?
finally
句内で戻り値を取得することは可能ですか?
これは理論的な質問なので、変数に保存するような回避策は探していません。
try
句内に return ステートメントがあります。
def f():
try:
return whatever()
finally:
pass # How do I get what `whatever()` returned in here?
finally
句内で戻り値を取得することは可能ですか?
これは理論的な質問なので、変数に保存するような回避策は探していません。
いいえ、そうではありません。finally
条項の内容は返品の仕組みとは無関係です。返される値を確認したい場合は、前述のようにして、スコープ内のどこかに明示的に保存する必要があります。
returnステートメントの後に絶対に「入る」必要がありますか?
ステートメントの前に変更が許可されている場合は、それだけで十分です。return
sys.settrace()
後 の値の取得return
:
スタックレスPython では、それができるはずです。「スレッド」はスタックレスでピクルすることができ、値スタックのトップとも呼ばれる、返される直前の値がそこにあるはずです。
CPythonでは、値スタックのトップを覗く方法がまだ見つかりませんでした。
もちろん、C レベルの拡張機能ですべてが可能です。簡単なデモを次に示します。ctypes
"""
valuestack.py: Demo reading values from Python value stack
Offsets are derived for CPython-2.7.2, 64-bit, production build
"""
import ctypes, inspect, random
def id2obj(i):
"""convert CPython `id` back to object ref, by temporary pointer swap"""
tmp = None,
try:
ctypes.cast(id(tmp), ctypes.POINTER(ctypes.c_ulong))[3] = i
return tmp[0]
finally:
ctypes.cast(id(tmp), ctypes.POINTER(ctypes.c_ulong))[3] = id(None)
def introspect():
"""pointer on top of value stack is id of the object about to be returned
FIXME adjust for sum(vars, locals) in introspected function
"""
fr = inspect.stack()[1][0]
print "caught", id2obj(ctypes.cast(id(fr), ctypes.POINTER(ctypes.c_ulong))[47])
def value():
tmp = random.random()
print "return", tmp
return tmp
def foo():
try:
return value()
finally:
introspect()
if __name__ == "__main__":
foo()
osx に同梱されている 64 ビット モードの Python-2.7.2 で動作します。
air:~ dima$ python valuestack.py
return 0.959725159294
caught 0.959725159294
不可能です。バイトコードを検査したり、フレーム オブジェクトをいじったりするなど、巨大でおかしなハックを検討している場合は、そうかもしれません。戻り値がローカルになく、フレームオブジェクトを介して中間値のスタック (戻り値が保存される場所) にアクセスできないと思うので、これが意味を成すかどうかもわかりません。
ctypes
おそらくC API に加えて使用することもできますが、それもおそらく非常に不安定であり、 の実装に精通している必要がありますfinally
。これがどれほど実現可能かを判断するのに十分な情報はありませんが、言うまでもなく、これはPythonコードでできることの範囲外です。
そして、戻り値がない可能性があるという追加の問題があります(whatever()
例外がスローされた場合)! を使用すると、その状態を簡単に検出できると思いますsys.exc_info()
。
def f():
InvalidFoo = object()
foo = InvalidFoo
try:
foo = whatever()
return foo
finally:
if foo is not InvalidFoo:
# look at foo