У меня есть имя функции, хранящееся в переменной вроде этого:
myvar = 'mypackage.mymodule.myfunction'
и теперь я хочу назвать myfunction следующим образом
myvar(parameter1, parameter2)
Какой самый простой способ достичь этого?
У меня есть имя функции, хранящееся в переменной вроде этого:
myvar = 'mypackage.mymodule.myfunction'
и теперь я хочу назвать myfunction следующим образом
myvar(parameter1, parameter2)
Какой самый простой способ достичь этого?
funcdict = {
'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
....
}
funcdict[myvar](parameter1, parameter2)
Намного лучше иметь возможность просто сохранить эту функцию, поскольку они являются первоклассными объектами в python.
import mypackage
myfunc = mypackage.mymodule.myfunction
myfunc(parameter1, parameter2)
Но если вам нужно импортировать пакет динамически, вы можете достичь этого через:
mypackage = __import__('mypackage')
mymodule = getattr(mypackage, 'mymodule')
myfunction = getattr(mymodule, 'myfunction')
myfunction(parameter1, parameter2)
Помните, однако, что вся эта работа применима к любой области, в которой вы сейчас находитесь. Если вы не будете их упорствовать, вы не можете рассчитывать на то, что они останутся, если вы покинете локальную область.
def f(a,b):
return a+b
xx = 'f'
print eval('%s(%s,%s)'%(xx,2,3))
OUTPUT
5
Самый простой
eval(myvar)(parameter1, parameter2)
У вас нет функции "указатель". У вас есть функция "имя".
Пока это работает хорошо, у вас будет большое количество людей, которые расскажут вам об этом "небезопасно" или о "угрозе безопасности".
Почему бы не сохранить функцию самостоятельно? myvar = mypackage.mymodule.myfunction
намного чище.
modname, funcname = myvar.rsplit('.', 1)
getattr(sys.modules[modname], funcname)(parameter1, parameter2)
eval(compile(myvar,'<str>','eval'))(myargs)
compile (..., 'eval') допускает только один оператор, поэтому после вызова не может быть никаких команд, или будет SyntaxError. Тогда крошечный бит валидации может по крайней мере ограничить выражение чем-то в вашей власти, например, начать тестирование "mypackage".
У меня возникла аналогичная проблема при создании библиотеки для проверки подлинности. Я хочу, чтобы владелец приложения, используя мою библиотеку, мог зарегистрировать обратный вызов с библиотекой для проверки авторизации в отношении групп LDAP, в которых находится аутентифицированный человек. Конфигурация передается как файл config.py, который импортируется и содержит dict с все параметры конфигурации.
Я получил это для работы:
>>> class MyClass(object):
... def target_func(self):
... print "made it!"
...
... def __init__(self,config):
... self.config = config
... self.config['funcname'] = getattr(self,self.config['funcname'])
... self.config['funcname']()
...
>>> instance = MyClass({'funcname':'target_func'})
made it!
Есть ли способ pythonic-er сделать это?