2014-09-24 277 views
1

我无法理解在Python(2.7.2)中如何装饰装饰器。我有以下一段代码:在Python中装饰装饰器

def verbose(function): 
    print 'i am verbose and func is ' + function.__name__ 
    def wrapper2(func): 
     print 'func is ' + repr(func) 
     result = function(func) 
     return result 
    return wrapper2 

@verbose 
def more(function): 
    print 'i am more and func is ' + function.__name__ 
    def wrapper1(*args, **kwargs): 
     print 'args' + repr(args) 
     result = function(*args) 
     return result 
    return wrapper1 

@more 
def hello(*args): 
    print(sum(args)) 

当我运行:

>>> hello(1,2,3) 

这就是我得到:

i am verbose and func is more 
func is <function hello at 0x1015338c0> 
i am more and func is hello  
args(1, 2, 3) 
6 

我无法想象调用序列生成此输出。我认为下面的调用仍然会生成相同的输出,我很想了解装饰器在这个特定示例中的工作方式。

>>> verbose(more)(hello)(1,2,3) 
i am verbose and func is more 
func is <function hello at 0x101533d70> 
i am more and func is hello 
args(1, 2, 3) 
6 
+1

由于您在尝试在定义之前使用装饰器,因此您的代码会生成NameError。你真的在'more'上面定义了'verbose'吗?另外,即使你这样做了,你显示的一些输出将会在'hello'被定义时产生,有些时候'more'被定义,而不是当'hello'被调用时。在你的例子中,什么是'python >>'提示符? – BrenBarn 2014-09-24 06:57:00

+0

修复名称错误。是的,当我定义'more'和一些定义'hello'方法时,会产生输出的一部分。我只是在这里粘贴,以确保两种调用方式生成相同的输出。 – Codenobar 2014-09-24 07:06:18

回答

0

您还原为verbose(more)(hello)(1,2,3)是正确的。但是,这些呼叫发生在不同的时间。记住这一点:

@deco 
def func(): 
    # whatever 

是一样的:

def func(): 
    # whatever 
func = deco(func) 

所以当你定义moreverbose被调用。当您定义hello时,将调用more(装饰版)。您的代码相当于:

def verbose(function): 
    print 'i am verbose and func is ' + function.__name__ 
    def wrapper2(func): 
     print 'func is ' + repr(func) 
     result = function(func) 
     return result 
    return wrapper2 

def more(function): 
    print 'i am more and func is ' + function.__name__ 
    def wrapper1(*args, **kwargs): 
     print 'args' + repr(args) 
     result = function(*args) 
     return result 
    return wrapper1 
more = verbose(more) 

def hello(*args): 
    print(sum(args)) 
hello = more(hello) 

这应该说明哪些函数调用正在发生时。请注意,当您调用hello(1, 2, 3)时,moreverbose都不会被调用。当装饰函数是定义为时,调用装饰器时不会调用它。在通话时,所谓的装饰器的返回值(即在您的示例中的功能wrapper1wrapper2)。

+0

谢谢@BrenBarn – Codenobar 2014-09-24 08:25:02