2010-02-17 2 views
54

У меня есть имя функции, хранящегося в переменной, как это:Python указатель функции

myvar = 'mypackage.mymodule.myfunction' 

и теперь я хочу назвать MyFunction как этот

myvar(parameter1, parameter2) 

Что самый простой способ для достижения этой цели?

+4

Почему бы не сохранить функцию самостоятельно? 'myvar = mypackage.mymodule.myfunction' намного чище. – ironfroggy

+1

Из комментария ниже: «Это должна быть строка, потому что в том месте, где она определена, приложение не знает нужную функцию, так как это общее приложение». - schneck – badp

ответ

81
funcdict = { 
    'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction, 
    .... 
} 

funcdict[myvar](parameter1, parameter2) 
+1

+1 Отличный ответ. –

+0

Наконец, ваше решение лучше всего подходит мне, спасибо. – schneck

+0

Интересно, что такое хиты производительности здесь, если функция будет называться много раз (в цикле, рекурсии и т. Д.)? – zanlok

7

Самый простой

eval(myvar)(parameter1, parameter2) 

Вы не имеют функции "указатель". У вас есть функция «имя».

Хотя это хорошо работает, у вас будет большое количество людей, говорящих вам, что это «небезопасно» или «угроза безопасности».

+1

«небезопасный»: если myvar поступает с пользовательского ввода , да :) –

+20

Они будут «правы». –

+6

...и многие люди правы. – Triptych

13
def f(a,b): 
    return a+b 

xx = 'f' 
print eval('%s(%s,%s)'%(xx,2,3)) 

ВЫВОД

5 
+0

Я дам выдержку, чтобы противостоять нисходящему. Это может быть не лучшее решение, я думаю, что это полезный ответ, так как он показывает полный рабочий пример. –

+0

@ Брайан Окли приветствует! –

+4

eval - дьявол, imo – zanlok

4
modname, funcname = myvar.rsplit('.', 1) 
getattr(sys.modules[modname], funcname)(parameter1, parameter2) 
5

Почему бы не хранить саму функцию? myvar = mypackage.mymodule.myfunction намного чище.

33

Гораздо приятнее иметь возможность просто сохранить функцию, поскольку они являются первоклассными объектами в python.

import mypackage 

myfunc = mypackage.mymodule.myfunction 
myfunc(parameter1, parameter2) 

Но, если вы должны импортировать пакет динамически, то вы можете добиться этого с помощью:

mypackage = __import__('mypackage') 
mymodule = getattr(mypackage, 'mymodule') 
myfunction = getattr(mymodule, 'myfunction') 

myfunction(parameter1, parameter2) 

Имейте в виду, однако, что все эти работы относится к тому, что сфера вы в настоящее время Если вы не будете их упорствовать, вы не можете рассчитывать на то, что они останутся, если вы покинете местность.

1

eval(compile(myvar,'<str>','eval'))(myargs)

компиляции (..., «Eval») допускает только один оператор, так что не может быть произвольные команды после вызова, или будет SyntaxError. Тогда крошечная проверка может по крайней мере ограничить выражение чем-то в вашей власти, например, начать тестирование «mypackage».

1

У меня возникла аналогичная проблема при создании библиотеки для обработки аутентификации. Я хочу, чтобы владелец приложения, используя мою библиотеку, мог зарегистрировать обратный вызов с библиотекой для проверки авторизации в отношении групп 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! 

Есть ли вещий-эр способ сделать это?