2017-09-21 42 views
0

以下是我試圖做的簡單示例。下面的函數'print_number'由2個裝飾器包裝。在Python中使用多個裝飾器執行每個裝飾器的原始功能

def another_decorator(function): 
    def wrapper(*arg, **kwargs): 
     ret = function(*arg, **kwargs) 
     print(ret, "executed from another_decorator") 
    return wrapper 

def test_decorator(function): 
    def wrapper(*arg, **kwargs): 
     ret = function(*arg, **kwargs) 
     print(ret, "executed from test_decorator") 
    return wrapper 

@another_decorator 
@test_decorator 
def print_number(num): 
    return num 
x = print_number(222) 
print(x) 

以上的回報

222 executed from test_decorator 
None executed from another_decorator 
None 

正如你所看到的,只有test_decorator能夠執行包裹print_number功能。對這個函數的調用完全在another_decorator中跳過。 爲什麼我需要這個的一些背景。我有一些代碼,我用多個裝飾器包裝主異步函數,我需要調用每個裝飾器的異步函數。每個裝飾器都會進行一些初步工作,以傳遞給被調用的異步函數,其中創建aiohttp會話並使用ensure_future調度協程。 有沒有一種方法或可能的過程來調用每個裝飾器的包裝函數'函數'?

回答

1

實際上你需要在你的裝飾返回.. .additionally功能在Python只是對象,因此給你的包裝功能屬性「原始」

def another_decorator(function): 
    def wrapper(*arg, **kwargs): 
     ret = function(*arg, **kwargs) 
     print(ret, "executed from another_decorator") 
     return ret 
    wrapper.original = getattr(function,"original",function) 
    return wrapper 

def test_decorator(function): 
    def wrapper(*arg, **kwargs): 
     ret = function(*arg, **kwargs) 
     print(ret, "executed from test_decorator") 
     return ret 
    wrapper.original = getattr(function,"original",function) 
    return wrapper 
+0

感謝。這真的很有趣,這確實有效,雖然我很難看到這裏發生了什麼。我知道,在getattr中,由於'original'不存在於對象'function'中,因此您正在獲取默認的'function'值。我猶豫地承認檢索值'執行'功能和'print_number'功能被調用。但我不明白爲什麼這會起作用。以前,我使用functool.wraps並嘗試在'another_decorator'中執行函數.__包裝__(),但這種方法無效。 – user2993021