dkiselev dkiselev - 3 months ago 9
Python Question

Python decorators: howto list wrapped functions by decorator

Is that possible to use python decorators to mark a method, and get it for the later use, if I don't know the name of the wrapped function?

Here is the example, and I don't know the name of 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)


So how can I get a list of methods wrapped with
@run_this_method

Answer

If you need to track all functions and methods decorated with your decorator you need to create global variable to register all such functions and methods. I've modified your code:

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__)

Instead of using global variable functions_registry you can create class to be used as decorator and register functions in entity field. Something like this:

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__)