2016-08-26 4 views
1

Возможно ли использовать декораторы python для отметки метода и получить его для последующего использования, если я не знаю имени обернутой функции?Декораторы Python: howto перечисляет завернутые функции декоратором

Вот пример, и я не знаю имя method_with_custom_name:

@run_this_method 
def method_with_custom_name(my_arg): 
    return "The args is: " + my_arg 

def _init_and_run(): 
    # Here, I want to get and call method_with_custom_name 
    # but I don't know it's name, 
    # so the next line isn't valid. 
    return run_this_method()(my_arg_value) 

def run_this_method(m): 
    def w(my_arg): 
     _do_some_magic(my_arg, m) 
    return w 

def _do_some_magic(callback_arg, callback): 
    if some_checks(): 
      callback(callback_arg) 

Так как я могу получить список методов, обернутых @run_this_method

ответ

2

Если вам нужно отслеживать все функции и методы, украшенные вашим декоратором, вам необходимо создать глобальную переменную для регистрации всех таких функций и методов. Я изменил код:

funcs_registry = [] #List of all functions decorated with @run_this_method 
def run_this_method(m): 
    global functions_registry 
    funcs_registry.append(m) #Add function/method to the registry 

    def w(my_arg): 
     _do_some_magic(my_arg, m) 
    return w 

def _do_some_magic(callback_arg, callback): 
    if some_checks(): 
     callback(callback_arg) 

@run_this_method 
def method_with_custom_name(my_arg): 
    return "The args is: " + my_arg 

def _init_and_run(): 
    global functions_registry 

    # Here you can iterate over "functions_registry" 
    # and do something with each function/method in it 
    for m in functions_registry: 
     print(m.__name__) 

Вместо использования глобальной переменной functions_registry вы можете создать класс для использования в качестве декоратора и регистрации функций в области лица. Что-то вроде этого:

class FunDecorator: 
    def __init__(self): 
     self.registry = [] 

    def __call__(self, m): 
     "This method is called when some method is decorated" 
     self.registry.append(m) #Add function/method to the registry 

     def w(my_arg): 
      _do_some_magic(my_arg, m) 
     return w 

run_this_method = FunDecorator() #Create class instance to be used as decorator 

@run_this_method 
def method_with_custom_name(my_arg): 
    return "The args is: " + my_arg 

#do some magic with each decorated method: 
for m in run_this_method.registry: 
    print(m.__name__) 
+0

Нет, вам не нужно вводить глобальное состояние, чтобы сделать это, больше, чем вы когда-либо нужно ввести глобальное состояние для отслеживания всего в приложении. –

+0

Спасибо, что работает. – dkiselev

+0

@ Two-BitAlchemist, может уточнить, как это можно реализовать без глобального состояния? –

1

Если я правильно понимаю ваш вопрос (как украсить метод неизвестным именем?), тогда это вполне возможно.

@decorator 
def foo(bar): 
    pass 

является syntastic сахар для

def foo(bar): 
    pass 
foo = decorator(foo) 

Так что в вашем случае вы просто должны сделать:

method_with_custom_name = run_this_method(method_with_custom_name) 

Пример Предоставленный в заблуждение, однако. Почему вы не знаете имя method_with_custom_name? Это прямо здесь. Он называется method_with_custom_name. Чтобы использовать декорированную версию позже, вы просто вызываете метод__у__и_и_о_о_о_о_о_о_о_.

+0

Потому что, я пишу LIB, а кто-то будет писать '' method_with_custom_name' и another_method_with_custom_name' – dkiselev

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