与原始功能一起装饰,无需重新编写功能

Posted

技术标签:

【中文标题】与原始功能一起装饰,无需重新编写功能【英文标题】:Decorated function along with original, without having to re-write the function 【发布时间】:2014-12-15 23:32:27 【问题描述】:

如果我有一个装饰器和一个函数,但我想将装饰函数与该函数的未装饰版本一起使用,我会怎么做?

我没有太多使用装饰器,从我能找到的情况来看,似乎你必须写出 2 个单独的函数来完成此操作,或者以函数作为参数调用装饰器,这可能会有点令人困惑处理多个装饰器。

为了解决这个问题,我正在编写一个函数,然后我使用一种有点迂回的方式来装饰函数并在事后返回该装饰函数。所以我可以访问该函数的未装饰和装饰版本。据我所知,实现这一点的方法有点被看不起,但它一直对我有用到目前为止。我无法想象这是解决这个问题的最佳方式。

本质上,我将要装饰的函数与装饰器函数一起传递给检查函数文本的方法,将@decorator 语法添加到文本中,然后将装饰器函数添加到__builtins__模块暂时这样我就可以将exec 文本放入字典中来定义新的修饰函数。这个新的函数对象是从字典中提取出来的,并作为新的修饰函数返回。

我很确定这不是最好的解决方法。我不认为它适用于所有情况,但我也不想每次都调用修饰函数或重写函数。

【问题讨论】:

为什么不直接在需要的时候使用function(...),在需要装饰版的时候使用decorator(function)(...) @jonsharpe,我想知道是否还有其他方法可以做到这一点。我可以很容易地这样做,但我想我会问。 “应该有一种——最好只有一种——明显的方法” (import this),就是这样! 【参考方案1】:

那么不要将装饰器用作装饰器。请记住,装饰器是语法糖,但您没有必须使用它。

语法:

@decorator_expr
def decorated_func():
    pass

实际上是这样执行的:

def decorated_func():
    pass
decorated_func = decorator_expr(decorated_func)

要保留“原始”和修饰版本,只需将修饰器的输出分配给不同的名称:

def foo():
    pass

foo_decorated = decorator_expr(foo)

或者,每次需要装饰版本时使用可调用的装饰器:

result = decorator_expr(foo)()

【讨论】:

好的,我知道了。我意识到您可以使用函数作为相同行为的参数来调用装饰器,但我没有意识到您可以给它自己的可调用名称。谢谢! @DuckPuncher:在 Python 中,函数(和其他可调用对象,如绑定方法)是一流的对象,就像数字、字符串或其他任何东西一样。因此,您可以将它们分配给名称,通过这些名称调用它们,将它们作为参数传递给函数等。

以上是关于与原始功能一起装饰,无需重新编写功能的主要内容,如果未能解决你的问题,请参考以下文章

Java开发设计模式 09:装饰器模式

重新认识装饰模式--装饰模式实现AOP

装饰者模式

继承(实现)关系

Next.js 示例 Auth - 基于 auth 的重新路由,环绕其他功能

设计模式 - 适配器模式与装饰器模式? [复制]