инструкция exec с / без предварительной компиляции - PullRequest
1 голос
/ 25 мая 2009

В эти выходные я разбираю на куски модуль Мишеля Симонато , который создает декораторы, сохраняющие подпись. В основе всего этого лежит динамически генерируемая функция, которая работает примерно так ...

src = """def function(a,b,c) :\n    return _caller_(a,b,c)\n"""
evaldict = {'_caller_' : _caller_}
code = compile(src, '<string>', 'single')
exec code in evaldict
new_func = evaldict[function]

Я обнаружил, шутя с этим кодом, что шаг компиляции можно полностью избежать и перейти к одному:

exec src in evaldict

Теперь я уверен, что есть веская причина для этого дополнительного шага, но я не смог найти разницу между этими двумя подходами. Производительность

И поскольку я спрашиваю, можно ли с помощью eval добиться чего-то подобного, то есть определить новую функцию и получить к ней дескриптор? Я пытался, но не мог заставить это работать ...

Ответы [ 2 ]

2 голосов
/ 25 мая 2009

compile () позволяет вам управлять созданным объектом кода, его именем и источником, в то время как exec не настолько гибок. также стоит сделать так, чтобы другие, читая ваш код, узнали, что они являются отдельными шагами, и помнят об этом позже, когда им нужно выполнить один и тот же код более одного раза (где compile () один раз, exec несколько раз быстрее), и написание кода для просвещения следующего, кто его прочитает, всегда окажет достойное влияние на выбор дизайна.

2 голосов
/ 25 мая 2009

Есть несколько отличий, которые я вижу. Во-первых, compile имеет немного лучшую семантику при синтаксических ошибках, чем exec. Я подозреваю, что настоящая причина в том, что определение compile очень явно в отношении обработки символов новой строки, где exec немного менее точно.

Мне было любопытно, почему compile и exec используются вместо внутренних функций. Я не знал, что compile / exec позволяет вам контролировать, какие глобальные переменные доступны. Очень интересно.

...