【问题标题】:How to dynamically generate a list of functions with a decorator如何使用装饰器动态生成函数列表
【发布时间】:2019-08-27 11:27:24
【问题描述】:

我在一个模块中有一系列函数,例如

def some_func1(param1, param2): pass
def another_func(param1, param2): pass

我想要最简单的方法将它们添加到调用函数列表中,然后通过过滤器在某个点调用它们中的一些,并带有参数。我尝试使用装饰器添加到函数列表中,如下所示:

all_func = {}

def decorator(filter):
    def function_decorator(func):
        def wrapped(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapped

    all_func[filter] = function_decorator
    return function_decorator

@decorator(filter='1')
def some_func1(param1, param2): pass

@decorator(filter='2')
def another_func(param1, param2): pass

@decorator(filter='3')
def another_big_func(param1, *arg): pass

然后在使用带有过滤器的循环时,调用匹配过滤器的函数:

arg1 = some_obj
arg2 = another_obj
for i in range(3, 4):
    func = all_func.get(i)
    func(arg1, arg2)

也就是说,在添加一个函数的时候,我只是规定了一个新的过滤器值,并不关心我需要在某个地方注册其他东西,然后我在这个过滤器上调用它们

但是出了点问题,在all_func.get (i) 的时候我得到一个function_decorator,不是一个函数,我不明白如何用给定的参数调用它。

我以前没有使用过装饰器,也许我误解了这个概念。

【问题讨论】:

  • 你的意思是像宏记录吗??
  • 对不起,我不知道宏记录是什么。这段代码是一个大型 python 项目的一部分,所需的函数列表被传递给另一个类,这些函数将被调用
  • @ΦXocę웃Пepeúpaツ:不,不像宏。
  • 请注意,您的 all_func 对象是字典,而不是列表,并且在使用字符串注册函数然后使用整数查找函数时,您将找不到函数。但是,这可能只是创建问题时的翻译错误。

标签: python decorator


【解决方案1】:

您注册了 装饰器,而不是包装器。请注意,您命名为decorator() 的东西实际上是一个装饰器工厂,调用decorator(...) 会生成装饰器函数function_decorator()。然后Python调用function_decorator()函数来做实际的装饰任务,它的返回值用来替换被装饰的函数。您想注册该过程的结果,而不是 function_decorator 本身。

注册包装器wrapped(),而不是:

def decorator(filter):
    def function_decorator(func):
        def wrapped(*args, **kwargs):
            return func(*args, **kwargs)
        all_func[filter] = wrapped
        return wrapped
    return function_decorator

现在all_func.get(i) 将返回wrapped() 函数之一。调用 wrapped() 然后通过 func 引用调用修饰函数。

您的wrapper() 确实是空操作,因此可以省略。装饰器必须返回替换函数,原始函数可以原样返回。使用 func 引用添加到您的注册表:

def decorator(filter):
    def function_decorator(func):
        all_func[filter] = func
        return func
    return function_decorator

请注意,您没有列表,您有一个字典,即从键到值的映射。这与问题无关。

【讨论】:

    【解决方案2】:

    有点不相关(参见 Martijn 对核心问题的回答),但是:

    1/ all_funcsdict,而不是 list

    2/ 如果您在填充 dict 时使用字符串作为键(@decorator(filter='1'),您也必须使用字符串作为键来恢复您的函数(range() 产生整数,而不是字符串),所以你想要

    for key in map(str, range(3, 4)):
        func = all_funcs.get(key)
    

    【讨论】:

      猜你喜欢
      • 2021-06-22
      • 2017-06-19
      • 2019-08-08
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-23
      • 2014-12-26
      相关资源
      最近更新 更多