【问题标题】:Decorating Multiple Python Functions装饰多个 Python 函数
【发布时间】:2021-02-01 16:00:59
【问题描述】:

假设我有很多对互补的功能:

def comp_func1(arg1, arg2):
    return f"comp_func1 {arg1} {arg2}"

def func1(arg1, arg2, flag=True):
    if flag:
        return f"func1 {arg1} {arg2}"
    else:
        return comp_func1(arg1, arg2)

def comp_func2(arg1, arg2):
    return f"comp_func2 {arg1} {arg2}"

def func2(arg1, arg2, flag=True):
    if flag:
        return f"func2 {arg1} {arg2}"
    else:
        return comp_func2(arg1, arg2)

本质上,对于每个函数funcX,如果flag == True 则返回函数详细信息,但如果flag == False 则调用其补充函数comp_funcX,该函数返回补充函数详细信息。

不必在每个funcX 中使用if/else 语句,是否可以使用装饰器来清理或简化此代码?大致如下:

def decorator():
    """
    Check the `flag` and choose whether to call the complementary function
    """
    def wrapper():
        if flag:
            return func(arg1, arg2)
        else:
            return comp_func(args, arg2) 
    return wrapper

def comp_func1(arg1, arg2):
    return f"comp_func1 {arg1} {arg2}"

@decorator(comp_func1)
def func1(arg1, arg2, flag=True):
    return f"func1 {arg1} {arg2}"

def comp_func2(arg1, arg2):
    return f"comp_func2 {arg1} {arg2}"

@decorator(comp_func2)
def func2(arg1, arg2, flag=True):
    return f"func2 {arg1} {arg2}"

【问题讨论】:

  • 除了你的装饰器中缺少一些细节,你没有说它有什么问题。看来您正在寻找替代解决方案...

标签: python python-decorators


【解决方案1】:

这样的?

def some_decorator(comp_function):
    def decorator_with_argument(function):
        def wrapper(*args, **kwargs):
            if kwargs.get("flag", False):
                return function(*args, **kwargs)
            else:
                return comp_function(*args, **kwargs)
        return wrapper
    return decorator_with_argument


def comp_func1(arg1, arg2, *_, **__):
    return f"comp_func1 {arg1} {arg2}"


@some_decorator(comp_func1)
def func1(arg1, arg2, *_, **__):
    return f"func1 {arg1} {arg2}"

wrapper函数通常取*args**kwargs,所以更通用。

【讨论】:

  • 啊,我写答案的速度太慢了!不过,您已经翻转了 functioncomp_functionsome_decorator 应采用 comp_function 作为参数,decorator_with_argument 应采用 function
  • 我建议不要将func1 的参数硬编码在wrapper 中,而是将func1 中的flag 更改为仅关键字参数:func1(arg1, arg2, *, flag=True):,然后更改@ 987654336@to: def wrapper(*args, **kwargs):kwargs.get("flag", False) if 语句代替。
【解决方案2】:

一个稍微不同的方法是使用一个简单的包装函数而不是一个成熟的装饰器。将所有函数和补充函数打包在相应的列表中,并通过带有索引的包装器调用您的函数:

funcs = [func1, func2, ...]
comps = [comp_func1, comp_func2, ...]

def wrapper(i, arg1, arg2, flag):
    if flag:
        return funcs[i-1](arg1, arg2)
    else:
        return comps[i-1](arg1, arg2)

现在拨打func1,您只需拨打:

wrapper(1, arg1, arg2, flag)

这是基于在第二个代码块中实现的功能。即每个函数都返回其对应的数据 - 其中没有 flag 条件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-18
    • 2013-06-15
    • 2014-07-21
    • 2012-11-05
    • 2017-01-15
    • 2022-01-01
    • 2019-11-05
    • 2016-09-13
    相关资源
    最近更新 更多