2016-05-07 1 views
1
code = "def foo(): return 'bar'" 

def lol(code): 
    exec code 
    return foo 

a = lol(code) 
print a() 

Это нормально работает, но проблема начинается, когда мы не знаем, как вызывается функция в строке. Если я могу гарантировать, что код будет небольшим, с одной функцией, как я могу вернуть эту функцию?Возврат функции неизвестного имени из функции

Одно из решений, о которых я думал, просто требовало, чтобы функция называлась «foo» и т. Д., Поэтому я могу просто вернуть это, но это кажется уродливым.

Мысли?

+0

Использование 'exec' для генерации динамического кода как правило, неодобрительно. Я бы пересмотрел код таким образом, чтобы он не нуждался в 'exec'. – hek2mgl

+0

Я не могу придумать другой способ оценить строку в коде Python. – Awn

ответ

1

Вы можете сделать это, указав явные словари exec для использования в контексте глобального и локального выполнения. Впоследствии, используемый для местных жителей, должен быть один элемент для объекта функции, который может быть возвращен без знания его имени, поскольку он должен быть единственным элементом, определенным в словаре:

from textwrap import dedent 
import types 

def lol(code): 
    globals_ = {"__builtins__": None} # no built-ins for safety 
    locals_ = {} 

    exec(code, globals_, locals_) 

    if len(locals_) != 1: 
     raise ValueError("code didn't define exactly one item") 
    value = locals_.popitem()[1] # get value of the one item defined 
    if type(value) != types.FunctionType: 
     raise ValueError("code didn't define a function") 

    return value # return function object that was defined 

my_code = dedent(""" 
    def foo(): 
     return 'bar' 
""") 

a = lol(my_code) 
print(a()) 
+0

Должно ли это иметь тот же вывод на обеих версиях Python? – Awn

+1

Вам нужно будет изменить последнюю строку на 'print (a())', потому что 'print' является функцией в Python 3, а не оператором, но в остальном она работает одинаково в обеих версиях. Я намеренно использовал кортежную форму 'exec', потому что он обеспечивает совместимость с Python 3. – martineau

+0

Знаете ли вы, каким образом я мог бы обрабатывать, если строка кода содержит более одной функции? – Awn

 Смежные вопросы

  • Нет связанных вопросов^_^