1. 程式人生 > >python語言特性之裝飾器

python語言特性之裝飾器

首先,python裝飾器的作用是:在不改變原有函式實現的前提下,給此函式增加一些額外的功能(在原有函式呼叫之前或者呼叫之後),好像給原有函式加上了一個裝飾的殼子

通過一個例子解釋python裝飾器:

# -*- coding:utf8 -*-

def w1(func):
    def inner(*args,**kwargs):
        print 'w1'
        func(*args,**kwargs)
        print func
    return inner
 
def w2(func):
    print func
    def inner(*args,**kwargs):
        print 'w2'
        func(*args,**kwargs)
    return inner

def w3(func):
    print func
    def inner(*args,**kwargs):
        print 'w3'
        func(*args,**kwargs)
    return inner

@w3
@w2
@w1
def f1(arg1,arg2,arg3):
    print 'f1'

f1(1,2,3)

以上是python多個裝飾器使用的例子,目的是為了更好說明裝飾器、以及裝飾器鏈的使用,裝飾器函式的呼叫順序等等。

那麼,在使用三個裝飾器裝飾f1函式,會怎麼執行呢,結果如何呢?

首先需要明確一個概念,函式和函式的呼叫

以上程式碼中:f1、w1、w2、w3、inner等都是函式,函式其實在記憶體中就是一個地址。f1(1,2,3)是函式呼叫。很簡單的問題,很容易理解。

第二個概念:語法糖。(@函式名來裝飾函式名  只舉一個例子:

@w1
def f1(arg1,arg2,arg3):
    print 'f1'

以上程式碼相當於

def f1(arg1,arg2,arg3):
    print 'f1'

f1 = w1(f1)

注意:f1 = w1(f1) 中,作為引數的f1和返回的f1 已經不是同一個f1了。

好,先看看執行結果:

疑問1:w1 w2 w3三個裝飾器的執行順序是怎麼樣的?

疑問2:為什麼呼叫了三次裝飾器,只調用了一次f1,不應該每呼叫一次w就呼叫一次f1嗎?

第一個疑問:多個裝飾器的呼叫順序是自下往上,但是執行時的執行順序是自上往下!其實只需要記住呼叫順序是自下往上,執行順序可以從呼叫順序推出來!同理第二個疑問也可以通過相同辦法推出來。

根據以上語法糖的解釋,根據自下往上的呼叫順序,函式裝飾器還可以表示為以下方式:

def f1(arg1,arg2,arg3):     print 'f1'

f1 = w1(f1) #1 把以上f1作為引數傳給w1,再把函式返回值傳回給f1(相當於給f1賦了新值,新的值為w1的返回值inner)

f1 = w2(f1) #2 把inner(注意,此時f1已經是w1的返回值inner)作為引數傳給w2,並且給f1重新賦新值

f1 = w3(f1) #3 把w2的返回值inner作為引數傳給f1,並且給f1重新賦值(w3的返回值inner)

為了更加清楚說明,我們翻譯如下:

f1 = w1(最初f1)

f1 = w2(w1函式返回值inner)

f1 = w3(w2函式返回值inner)

此時,我們呼叫函式f1(1,2,3),其實就是呼叫了w3裡面的inner函式。但是給w3傳的引數是w2的返回值inner。等呼叫到w3中func(*args,**kwargs)函式的時候,其實是呼叫了w2的內層函式inner。以此類推,直到呼叫w1內部的func(*args,**kwargs)函式的時候,才是呼叫的最初的f1函式,所以,其實f1函式只調用了一次,而且是按照w3、w2、w1、f1的順序執行。

以上就是python裝飾器的使用。