У мене є ім'я функції, яке зберігається у такій змінній:
myvar = 'mypackage.mymodule.myfunction'
і я зараз хочу зателефонувати до своєї функції таким чином
myvar(parameter1, parameter2)
Який найпростіший спосіб цього досягти?
У мене є ім'я функції, яке зберігається у такій змінній:
myvar = 'mypackage.mymodule.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))
ВИХІД
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!
Чи існує пітонічний спосіб зробити це?
myvar = mypackage.mymodule.myfunction
набагато чистіше.