1.5.3 Python裝飾器

花姐毛毛腿發表於2019-01-19

一、簡單的裝飾器

為什麼要使用裝飾器呢?  裝飾器的功能:在不修改原函式及其呼叫方式的情況下對原函式功能進行擴充套件  裝飾器的本質:就是一個閉包函式那麼我們先來看一個簡單的裝飾器:實現計算每個函式的執行時間的功能

import timedef wrapper(func):    def inner():        start = time.time()        func()        end = time.time()        print(end - start)    return innerdef hahaha():    time.sleep(1)    print('aaaaa')hahaha = wrapper(hahaha)hahaha()複製程式碼

上面的功能有點不簡介,不完美,下面就引進了語法糖。

import timedef wrapper(func):    def inner():        start = time.time()        func()        end = time.time()        print(end - start)    return inner@wrapperdef kkk():  ## 相當於kkk=wrapper(kkk)    print('aaaaa')kkk()複製程式碼

以上的裝飾器都是不帶引數的函式,現在裝飾一個帶引數的該怎麼辦呢原函式帶多個引數的裝飾器

import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        end=time.time()        print(end- start)        return re    return inner@timer   #**>
func1 = timer(func1)
def func1(a,b): print('in func1') print(a,b)@timer #**>
func1 = timer(func1)
def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over'func1(1,2)print(func2('aaaaaa'))複製程式碼

帶返回值的裝飾器

import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        end=time.time()        print(end - start)        return re    return inner@timer   #**>
func1 = timer(func1)
def jjj(a): print('in jjj and get a:%s'%(a)) return 'fun2 over'jjj('aaaaaa')print(jjj('aaaaaa'))複製程式碼

二、開放封閉原則

1.對擴充套件是開放的2.對修改是封閉的

三、裝飾器的固定結構

import timedef wrapper(func):  ## 裝飾器    def inner(*args, **kwargs):        '''函式執行之前的內容擴充套件'''        ret = func(*args, **kwargs)         '''函式執行之前的內容擴充套件'''        return ret    return inner@wrapper  ## ****=>
aaa=timmer(aaa)
def aaa(): time.sleep(1) print('fdfgdg')aaa()複製程式碼

四、帶引數的裝飾器

帶引數的裝飾器:就是給裝飾器傳參用處: 就是當加了很多裝飾器的時候,現在忽然又不想加裝飾器了,想把裝飾器給去掉了,但是那麼多的程式碼,一個一個的去閒的麻煩,那麼,我們可以利用帶引數的裝飾器去裝飾它,這就他就像一個開關一樣,要的時候就呼叫了,不用的時候就去掉了。給裝飾器裡面傳個引數,那麼那個語法糖也要帶個括號。在語法糖的括號內傳參。在這裡,我們可以用三層巢狀,弄一個標識為去標識。如下面的程式碼示例

## 帶引數的裝飾器:(相當於開關)為了給裝飾器傳參## F=True#為True時就把裝飾器給加上了F=False#為False時就把裝飾器給去掉了def outer(flag):    def wrapper(func):        def inner(*args,**kwargs):            if flag:                print('before')                ret=func(*args,**kwargs)                print('after')            else:                ret = func(*args, **kwargs)            return ret        return inner    return wrapper@outer(F)#@wrapperdef hahaha():    print('hahaha')@outer(F)def shuangwaiwai():    print('shuangwaiwai')hahaha()shuangwaiwai()給裝飾器加引數複製程式碼

五、多個裝飾器裝飾一個函式

def qqqxing(fun):    def inner(*args,**kwargs):        print('in qqxing: before')        ret = fun(*args,**kwargs)        print('in qqxing: after')        return ret    return innerdef pipixia(fun):    def inner(*args,**kwargs):        print('in qqxing: before')        ret = fun(*args,**kwargs)        print('in qqxing: after')        return ret    return inner@qqqxing@pipixiadef dapangxie():    print('餓了嗎')dapangxie()'''@qqqxing和@pipixia的執行順序:先執行qqqxing裡面的 print('in qqxing: before'),然後跳到了pipixia裡面的        print('in qqxing: before')        ret = fun(*args,**kwargs)        print('in qqxing: after'),完了又回到了qqqxing裡面的 print('in qqxing: after')。所以就如下面的執行結果截圖一樣'''多個裝飾器裝飾一個函式複製程式碼

六、統計多少個函式被裝飾了的小應用

l=[]def wrapper(fun):    l.append(fun)#統計當前程式中有多少個函式被裝飾了    def inner(*args,**kwargs):        ## l.append(fun)#統計本次程式執行有多少個帶裝飾器的函式被呼叫了        ret = fun(*args,**kwargs)        return ret    return inner@wrapperdef f1():    print('in f1')@wrapperdef f2():    print('in f2')@wrapperdef f3():    print('in f3')print(l)複製程式碼

來源:https://juejin.im/post/5c4343daf265da61285a636b

相關文章