2010-10-06 113 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只被重新分配一次。