web-dev-qa-db-ja.com

関数のコードオブジェクトでPython execを使用しているときに戻り値を取得するにはどうすればよいですか?

テスト目的で、別の関数の内部で定義された関数を直接実行したいと思います。

親関数のコード(func_code)を介して子関数のコードオブジェクトに到達できますが、実行すると戻り値が返されません。

実行されたコードから戻り値を取得する方法はありますか?

27
user2433423

はい、execステートメント内に割り当てが必要です。

>>> def foo():
...     return 5
...
>>> exec("a = foo()")
>>> a
5

これは制御されたテストで使用されているため、おそらくあなたのケースには関係ありませんが、ユーザー定義の入力でexecを使用する場合は注意してください。

18
wnnmaw

このような何かがうまくいくことができます:

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)で関数コンストラクターに渡す必要があります。

3
georg

これは人類がこれまでに見た中で最も醜い獣ですが、これはexec呼び出し内でグローバル変数を使用して行うことができる方法です。

def my_exec(code):
    exec('global i; i = %s' % code)
    global i
    return i

これは、グローバル変数を誤用して、国境を越えてデータを取得することです。

>>> my_exec('1 + 2')
3

言うまでもないことですが、neverこの関数の入力にはユーザー入力を許可してください。これは、極端なセキュリティリスクをもたらすためです。

2
devsnd