テスト目的で、別の関数の内部で定義された関数を直接実行したいと思います。
親関数のコード(func_code)を介して子関数のコードオブジェクトに到達できますが、実行すると戻り値が返されません。
実行されたコードから戻り値を取得する方法はありますか?
はい、exec
ステートメント内に割り当てが必要です。
>>> def foo():
... return 5
...
>>> exec("a = foo()")
>>> a
5
これは制御されたテストで使用されているため、おそらくあなたのケースには関係ありませんが、ユーザー定義の入力でexec
を使用する場合は注意してください。
このような何かがうまくいくことができます:
def outer():
def inner(i):
return i + 10
for f in outer.func_code.co_consts:
if getattr(f, 'co_name', None) == 'inner':
inner = type(outer)(f, globals())
# can also use `types` module for readability:
# inner = types.FunctionType(f, globals())
print inner(42) # 52
アイデアは、内部関数からコードオブジェクトを抽出し、それに基づいて新しい関数を作成することです。
内部関数に自由変数を含めることができる場合は、追加の作業が必要です。それらも抽出し、最後の引数(closure
)で関数コンストラクターに渡す必要があります。
これは人類がこれまでに見た中で最も醜い獣ですが、これはexec呼び出し内でグローバル変数を使用して行うことができる方法です。
def my_exec(code):
exec('global i; i = %s' % code)
global i
return i
これは、グローバル変数を誤用して、国境を越えてデータを取得することです。
>>> my_exec('1 + 2')
3
言うまでもないことですが、neverこの関数の入力にはユーザー入力を許可してください。これは、極端なセキュリティリスクをもたらすためです。