久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

python裝飾器詳解

 無憂無慮1n684t 2020-02-20
你會(huì)Python嘛,?
我會(huì),!
那你給我講下Python裝飾器吧,!
Python裝飾器???我沒用過哎

以上是我一個(gè)哥們面試時(shí)候發(fā)生的真實(shí)對(duì)白,。

----------------------------------------------分割線------------------------------------------------------------------------------

簡(jiǎn)言之,python裝飾器就是用于拓展原來函數(shù)功能的一種函數(shù),,這個(gè)函數(shù)的特殊之處在于它的返回值也是一個(gè)函數(shù),,使用python裝飾器的好處就是在不用更改原函數(shù)的代碼前提下給函數(shù)增加新的功能。
一般而言,我們要想拓展原來函數(shù)代碼,,最直接的辦法就是侵入代碼里面修改,,例如:

import time
def func():
    print("hello")
    time.sleep(1)
    print("world")

這是我們最原始的的一個(gè)函數(shù),然后我們?cè)噲D記錄下這個(gè)函數(shù)執(zhí)行的總時(shí)間,,那最簡(jiǎn)單的做法就是:

#原始侵入,,篡改原函數(shù)
import time
def func():
    startTime = time.time()
    
    print("hello")
    time.sleep(1)
    print("world")
    endTime = time.time()
    
    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)

但是如果你的Boss在公司里面和你說:“小祁,這段代碼是我們公司的核心代碼,,你不能直接去改我們的核心代碼,。”那該怎么辦呢,,我們仿照裝飾器先自己試著寫一下:

#避免直接侵入原函數(shù)修改,,但是生效需要再次執(zhí)行函數(shù)
import time

def deco(func):
    startTime = time.time()
    func()
    endTime = time.time()
    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)


def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func
    deco(f)#只有把func()或者f()作為參數(shù)執(zhí)行,新加入功能才會(huì)生效
    print("f.__name__ is",f.__name__)#f的name就是func

這里我們定義了一個(gè)函數(shù)deco,,它的參數(shù)是一個(gè)函數(shù),,然后給這個(gè)函數(shù)嵌入了計(jì)時(shí)功能。然后你可以拍著胸脯對(duì)老板說,,看吧,,不用動(dòng)你原來的代碼,我照樣拓展了它的函數(shù)功能,。
然后你的老板有對(duì)你說:“小祁,,我們公司核心代碼區(qū)域有一千萬個(gè)func()函數(shù),從func01()到func1kw(),按你的方案,,想要拓展這一千萬個(gè)函數(shù)功能,,就是要執(zhí)行一千萬次deco()函數(shù),,這可不行呀,,我心疼我的機(jī)器?!?br>好了,,你終于受夠你老板了,準(zhǔn)備辭職了,,然后你無意間聽到了裝飾器這個(gè)神器,,突然發(fā)現(xiàn)能滿足你閆博士的要求了。
我們先實(shí)現(xiàn)一個(gè)最簡(jiǎn)陋的裝飾器,,不使用任何語法糖和高級(jí)語法,,看看裝飾器最原始的面貌:

#既不需要侵入,也不需要函數(shù)重復(fù)執(zhí)行
import time

def deco(func):
    def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func #這里f被賦值為func,,執(zhí)行f()就是執(zhí)行func()
    f()

這里的deco函數(shù)就是最原始的裝飾器,,它的參數(shù)是一個(gè)函數(shù),然后返回值也是一個(gè)函數(shù)。其中作為參數(shù)的這個(gè)函數(shù)func()就在返回函數(shù)wrapper()的內(nèi)部執(zhí)行,。然后在函數(shù)func()前面加上@deco,,func()函數(shù)就相當(dāng)于被注入了計(jì)時(shí)功能,現(xiàn)在只要調(diào)用func(),,它就已經(jīng)變身為“新的功能更多”的函數(shù)了,。
所以這里裝飾器就像一個(gè)注入符號(hào):有了它,拓展了原來函數(shù)的功能既不需要侵入函數(shù)內(nèi)更改代碼,,也不需要重復(fù)執(zhí)行原函數(shù),。

#帶有參數(shù)的裝飾器
import time

def deco(func):
    def wrapper(a,b):
        startTime = time.time()
        func(a,b)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

if __name__ == '__main__':
    f = func
    f(3,4)
    #func()

然后你滿足了Boss的要求后,,Boss又說:“小祁,,我讓你拓展的函數(shù)好多可是有參數(shù)的呀,有的參數(shù)還是個(gè)數(shù)不定的那種,,你的裝飾器搞的定不,?”然后你嘿嘿一笑,深藏功與名,!

#帶有不定參數(shù)的裝飾器
import time

def deco(func):
    def wrapper(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

@deco
def func2(a,b,c):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b+c))


if __name__ == '__main__':
    f = func
    func2(3,4,5)
    f(3,4)
    #func()

最后,,你的老板說:“可以的,,小祁,我這里一個(gè)函數(shù)需要加入很多功能,,一個(gè)裝飾器怕是搞不定,,裝飾器能支持多個(gè)嘛"
最后你就把這段代碼丟給了他:

#多個(gè)裝飾器

import time

def deco01(func):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper

def deco02(func):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        func(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))



if __name__ == '__main__':
    f = func
    f(3,4)
    #func()

'''
this is deco01
this is deco02
hello,,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

多個(gè)裝飾器執(zhí)行的順序就是從最后一個(gè)裝飾器開始,,執(zhí)行到第一個(gè)裝飾器,再執(zhí)行函數(shù)本身,。

盜用評(píng)論里面一位童鞋的例子:

def dec1(func):  
    print("1111")  
    def one():  
        print("2222")  
        func()  
        print("3333")  
    return one  
  
def dec2(func):  
    print("aaaa")  
    def two():  
        print("bbbb")  
        func()  
        print("cccc")  
    return two  
 
@dec1  
@dec2  
def test():  
    print("test test")  
  
test()  

輸出:

aaaa  
1111  
2222  
bbbb  
test test  
cccc  
3333

裝飾器的外函數(shù)和內(nèi)函數(shù)之間的語句是沒有裝飾到目標(biāo)函數(shù)上的,,而是在裝載裝飾器時(shí)的附加操作。

17~20行是裝載裝飾器的過程,,相當(dāng)于執(zhí)行了test=dect1(dect2(test)),,此時(shí)先執(zhí)行dect2(test),結(jié)果是輸出aaaa,、將func指向函數(shù)test,、并返回函數(shù)two,然后執(zhí)行dect1(two),,結(jié)果是輸出1111,、將func指向函數(shù)two,、并返回函數(shù)one,然后進(jìn)行賦值,。

用函數(shù)替代了函數(shù)名test,。 22行則是實(shí)際調(diào)用被裝載的函數(shù),這時(shí)實(shí)際上執(zhí)行的是函數(shù)one,,運(yùn)行到func()時(shí)執(zhí)行函數(shù)two,,再運(yùn)行到func()時(shí)執(zhí)行未修飾的函數(shù)test。

參考:Python 裝飾器:http://python./82344/

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多