2010-10-06 112 views
2

我装饰功能等的应用的正确顺序:Python的 - 装饰

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

这确实你所期望(适用于低水平装饰,然后做一些更多的东西我的问题。是,我现在想用functools.wraps,我不知道在哪里把它。这是我的猜测,但我不知道这是否会带来意想不到的后果。

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

(当然我申请wraps以内another_lower_level_decorator

回答

2

试试看:

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 

正如你可以看到它的工作原理!文档字符串在那里,分配的名称。

但这部作品一样的:

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

wraps只是修复了文档字符串/名称。只要所有装饰使用wraps,其中应用它的顺序无所谓

顺便说一句,有a much cooler decorator library

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 
+0

感谢。我认为你的第一种方式是正确的方式,通过阅读后。我意识到,如果在应用内部装饰器后使用'@wrap(func)',我假定内部装饰器也使用'wrapps(func)'。通过将它应用到装饰的'wrapper'函数中,我简单地将'wraps'功能应用到我的结果函数中,从而使事情更加明确(低级装饰器可能来自第三方等)。 – orokusaki 2010-10-06 18:26:47

1

是的,这对我来说很合适。 @another_lower_level_decorator将返回一个函数,其@wraps将包装,以便它具有与func相同的名称。

2

没错。其工作方式是

  • wrapper被定义。它调用func及其参数。
  • another_lower_level_decorator被调用,其中wrapper作为它的参数。它返回的函数成为新值wrapper
  • wraps(func)被调用来创建一个将应用名称/ docstring /等的包装。 func的任何函数被调用。
  • 返回值wraps(func),即生成的包装函数,通过当前值wrapper。请记住,这是another_lower_level_decorator的返回值。
  • wraps(func)(wrapper)成为wrapper的新值。
  • 该值由some_abstract_decorator返回,使该函数适合用作装饰器。

不管怎样,这是有效的。我认为在实践中wrapper只被重新分配一次。