Python 装饰器:如何通过装饰器列出包装函数

dki*_*lev 3 python python-decorators

如果我不知道包装函数的名称,是否可以使用 python 装饰器来标记方法并获取它以供以后使用?

这是示例,我不知道 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 Code Online (Sandbox Code Playgroud)

那么我怎样才能获得包含的方法列表@run_this_method

小智 6

如果您需要跟踪用装饰器装饰的所有函数和方法,您需要创建全局变量来注册所有此类函数和方法。我修改了你的代码:

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__)
Run Code Online (Sandbox Code Playgroud)

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__)
Run Code Online (Sandbox Code Playgroud)