2017-09-21 41 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