2014-09-24 284 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