如何在 python 中用我自己的包装第三方装饰器

Posted

技术标签:

【中文标题】如何在 python 中用我自己的包装第三方装饰器【英文标题】:How to wrap a third party decorator with my own in python 【发布时间】:2022-01-07 12:59:10 【问题描述】:

我看到很多用你自己的装饰器包装的例子,但它们都是关于自定义装饰器的。我有一个可以使用的第三方装饰器,例如:

@someSDK
myFunction()

我想要做的是将它包装在我自己的装饰器中,仅当 env 设置为 true 时才调用 @someSDK

编辑: 具体来说,第 3 方装饰者是 @xray_recorder.capture() 。我想要我自己的装饰器,只有当我有一个变量设置为某个标志时才会实现这个。

这是我目前的一个粗略想法:

if CUSTOM_XRAY_WRAPPER is True:
    @xray_recorder.capture()
    def wrapper(*args, **kwargs):
        val = func(*args, **kwargs)
        return val
    return wrapper
else:
    def wrapper(*args, **kwargs):
        val = func(*args, **kwargs)
        return val
    return wrapper

【问题讨论】:

【参考方案1】:

作为一个小例子,因为您没有提供最小的可重现示例:

CUSTOM_XRAY_WRAPPER = True

def xray_capture(func):
    def wrapper(*args, **kwargs):
        print('recodring')
        return func(*args, **kwargs)
    return wrapper

def yourdecorator(func):
    if CUSTOM_XRAY_WRAPPER:
        return xray_capture(func)
    return func

@yourdecorator
def yourfunction(text):
    print(text)

在这里,在函数上使用 xray_capture 装饰器会在执行该函数之前打印“记录”。如果 CUSTOM_XRAY_WRAPPER 为 False,函数 yourdecorator 可以用作装饰器,而不是返回正常函数。如果为 True,则返回用xray_capture 修饰的函数。

顺便说一句,您不必写 CUSTOM_XRAY_WRAPPER == True,因为它已经是 True 或 False,这意味着您正在检查是 True == True 还是 False == True

转移到你的例子,这看起来像这样:

def yourdecorator(func):
    if CUSTOM_XRAY_WRAPPER:
        xray_recorder.capture()(func)
    return func

【讨论】:

我在包装器之前添加注释的方式不正确吗? 嗯,你的版本肯定是不正确的。据我所知,您从未真正定义过真正的装饰器。你只定义一个包装函数。【参考方案2】:

你需要记住的是

@decorator
def foobar():
     ...

等价于

def foobar():
   ...
foobar = decorator(foobar)

所以你想要的是

def my_decorator(f):
    if CUSTOM_XRAY_WRAPPER:
       return xray_recorder.capture()(f)
    else:
       return f

【讨论】:

【参考方案3】:

您可以重命名装饰器并使用传递:

from functools import wraps


MY_ENV_VAR = True


# create a pass-through wrapper
def sample_decorator(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper


# now you can just use the same decorator everywhere
if MY_ENV_VAR:
    # use your recorder.capture 
    x_ray_capture = xray_recorder.capture()
else:
    # pass-through
    x_ray_capture = sample_decorator


@x_ray_capture
def foo():
    # do something

【讨论】:

第一个if不应该是xray_recorder.capture()吗? @qaispak 应该,已修复

以上是关于如何在 python 中用我自己的包装第三方装饰器的主要内容,如果未能解决你的问题,请参考以下文章

用于包装尝试的通用装饰器除了在 python 中?

python包装函数在装饰器中接受参数

如何让 sphinx 识别装饰的 python 函数

为啥 Python 的装饰器语法比普通的包装器语法提供更快的记忆代码?

Python:异常装饰器。如何保留堆栈跟踪

如何在 WPF 自定义装饰器中用线条排列拇指