Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-装饰器应用程序的正确顺序_Python_Decorator - Fatal编程技术网

Python-装饰器应用程序的正确顺序

Python-装饰器应用程序的正确顺序,python,decorator,Python,Decorator,我正在装饰这样一个函数: def some_abstract_decorator(func): @another_lower_level_decorator def wrapper(*args, **kwargs): # ... details omitted return func(*args, **kwargs) return wrapper 这正是您所期望的(应用一个低级修饰符,然后执行更多操作。我的问题是,我现在想使用functo

我正在装饰这样一个函数:

def some_abstract_decorator(func):
    @another_lower_level_decorator
    def wrapper(*args, **kwargs):
        # ... details omitted
        return func(*args, **kwargs)
    return wrapper
这正是您所期望的(应用一个低级修饰符,然后执行更多操作。我的问题是,我现在想使用
functools.wrapps
,但我不知道该放在哪里。这是我的猜测,但我不知道是否会产生意外后果

def some_abstract_decorator(func):
    @wraps(func)
    @another_lower_level_decorator
    def wrapper(*args, **kwargs):
        # ... details omitted
        return func(*args, **kwargs)
    return wrapper

(我当然在
另一个较低级别的修饰符
中应用
包装

是的,我看对了。
@另一个较低级别的修饰符
将返回一个函数,
@wrapps
将进行包装,使其与
func
同名。其工作方式如下

  • 定义了
    wrapper
    。它使用参数调用
    func
  • 调用另一个较低级别的修饰符
    ,其参数为
    包装器
    。它返回的函数成为
    包装器
    的新值
  • 调用
    wrapps(func)
    创建一个包装器,将
    func的名称/docstring/等应用于调用它的任何函数
  • wrapps(func)
    的返回值,即生成的包装函数,被传递给
    wrapper
    的当前值。记住,这是另一个较低级别的装饰器的返回值
  • wrapps(func)(wrapper)
    成为
    wrapper
    的新值
  • 该值由某个装饰器返回,使该函数适合用作装饰器
或者说实际上就是这样。我认为在实践中,
包装器
只被重新分配一次。

试试看:

from functools import wraps    

def another_lower_level_decorator(func):
    @wraps( func )
    def wrapped(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapped

def some_abstract_decorator(func):
    @wraps(func)
    @another_lower_level_decorator
    def wrapper(*args, **kwargs):
        # ... details omitted
        return func(*args, **kwargs)
    return wrapper


@some_abstract_decorator
def test():
    """ This is a docstring that should be on the decorated function """
    pass

help(test)
印刷品:

Help on function test in module __main__:

test(*args, **kwargs)
    This is a docstring that should be on the decorated function
正如您所看到的,它是有效的!docstring在那里,并且指定了名称

但这是一样的:

def some_abstract_decorator(func):
    @another_lower_level_decorator
    @wraps(func)
    def wrapper(*args, **kwargs):
        # ... details omitted
        return func(*args, **kwargs)
    return wrapper
wrapps
只修复docstring/名称。只要所有装饰程序都使用
wrapps
,应用它的顺序就不重要了

顺便说一句,有:


谢谢。我认为你的第一个方法是正确的,在阅读了这篇文章之后。我意识到如果我在应用内部装饰器后使用
@wrapps(func)
,我假设内部装饰器也使用
wrapps(func)
。通过将其应用于修饰的
包装器
函数,我只是将
包装器
功能应用于我的结果函数,从而使事情更加明确(低级装饰器可能来自第三方,等等)。
from decorator import decorator

@decorator
def another_decorator(func, *args, **kwargs):
    return func(*args, **kwargs)

@decorator
@another_decorator
def some_abstract_decorator(func, *args, **kwargs):
    # ... details omitted
    return func(*args, **kwargs)


@some_abstract_decorator
def test(x):
    """ this is a docstring that should be on the decorated function """
    pass