Как я могу динамически выполнять функцию в текущей области и добавлять ее как свойство вызывающей функции?

У меня есть код такой:

def f1(): <some stuff here> . . . @mylib.codegen def f2(args): f1() <some more stuff here> 

mylib.py:

 def codegen(fn): src = inspect.getsource(fn) original_ast = ast.parse(src) new_ast = transform_ast(original_ast) code_obj = compile(new_ast, '<auto-generated>', 'exec') myscope = {} exec code_obj in myscope fn.generated_fn = myscope['name'] # Where name is the binding created by execing code_obj 

Подводя итог, mylib.codegen – это декоратор, который разбирает код f, создает аспект другой функции, основанной на f , execs кода сгенерированной функции для получения вызываемой функции и устанавливает вызываемую функцию как свойство f . Это означает, что когда f2 импортируется в первый раз, f2 динамически получает другую функцию как свойство самого себя.

Сгенерированная функция также должна вызывать f1 но она не может найти f1 в myscope . Если бы какой-то Python разрешил встраивание, и у меня был встроенный код mylib.codegen , все было бы хорошо, но я не думаю, что Python позволяет встраивать код. Как я устанавливаю вещи так, чтобы сгенерированный объект кода выполнялся в пространстве имен функции вызывающего абонента?

fn.func_globals содержит глобальное пространство имен для данной функции; вам понадобится это, чтобы иметь возможность выполнить преобразованный и перекомпилированный объект кода:

 myscope = {} myscope.update(fn.func_globals) 

Не используйте fn.func_globals напрямую; вы не захотите переписывать элементы в этом пространстве имен.