最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python裝飾器原理與用法深入詳解

 更新時(shí)間:2019年12月19日 09:00:31   作者:nudt_qxx  
這篇文章主要介紹了python裝飾器原理與用法,結(jié)合實(shí)例形式深入分析了Python裝飾器的概念、原理、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了python裝飾器原理與用法。分享給大家供大家參考,具體如下:

你會(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ī)器?!?/p>

好了,你終于受夠你老板了,準(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。

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結(jié)》及《Python入門與進(jìn)階經(jīng)典教程

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • python控制臺(tái)中實(shí)現(xiàn)進(jìn)度條功能

    python控制臺(tái)中實(shí)現(xiàn)進(jìn)度條功能

    這篇文章主要介紹了python控制臺(tái)中實(shí)現(xiàn)進(jìn)度條功能的方法,想要了解的朋友可以參考一下
    2015-11-11
  • jupyter運(yùn)行時(shí)左邊一直出現(xiàn)*號(hào)問題及解決

    jupyter運(yùn)行時(shí)左邊一直出現(xiàn)*號(hào)問題及解決

    這篇文章主要介紹了jupyter運(yùn)行時(shí)左邊一直出現(xiàn)*號(hào)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 神經(jīng)網(wǎng)絡(luò)python源碼分享

    神經(jīng)網(wǎng)絡(luò)python源碼分享

    這篇文章主要介紹了神經(jīng)網(wǎng)絡(luò)python源碼分享,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • Django中Middleware中的函數(shù)詳解

    Django中Middleware中的函數(shù)詳解

    這篇文章主要介紹了Django中Middleware中的函數(shù)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • 詳解使用Selenium爬取豆瓣電影前100的愛情片相關(guān)信息

    詳解使用Selenium爬取豆瓣電影前100的愛情片相關(guān)信息

    這篇文章主要介紹了詳解使用Selenium爬取豆瓣電影前100的愛情片相關(guān)信息,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 詳解Python中四種關(guān)系圖數(shù)據(jù)可視化的效果對(duì)比

    詳解Python中四種關(guān)系圖數(shù)據(jù)可視化的效果對(duì)比

    python關(guān)系圖的可視化主要就是用來分析一堆數(shù)據(jù)中,每一條數(shù)據(jù)的節(jié)點(diǎn)之間的連接關(guān)系從而更好的分析出人物或其他場(chǎng)景中存在的關(guān)聯(lián)關(guān)系。本文將制作四個(gè)不同的關(guān)系圖的可視化效果,感興趣的可以了解一下
    2022-11-11
  • python實(shí)現(xiàn)遍歷文件夾修改文件后綴

    python實(shí)現(xiàn)遍歷文件夾修改文件后綴

    這篇文章主要介紹了python實(shí)現(xiàn)遍歷文件夾修改文件后綴,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • python快速安裝OpenCV的步驟記錄

    python快速安裝OpenCV的步驟記錄

    這篇文章主要給大家介紹了關(guān)于python快速安裝OpenCV的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 如何在PyCharm中配置使用Anaconda環(huán)境

    如何在PyCharm中配置使用Anaconda環(huán)境

    這篇文章主要介紹了如何在PyCharm中配置使用Anaconda環(huán)境,圖文講解寫的非常詳細(xì)簡(jiǎn)單易懂,還不會(huì)的小伙伴快來看看吧
    2023-03-03
  • Python爬蟲實(shí)現(xiàn)獲取動(dòng)態(tài)gif格式搞笑圖片的方法示例

    Python爬蟲實(shí)現(xiàn)獲取動(dòng)態(tài)gif格式搞笑圖片的方法示例

    這篇文章主要介紹了Python爬蟲實(shí)現(xiàn)獲取動(dòng)態(tài)gif格式搞笑圖片的方法,結(jié)合實(shí)例形式分析了Python針對(duì)gif格式圖片的爬取、下載等相關(guān)操作技巧,需要的朋友可以參考下
    2018-12-12

最新評(píng)論

北票市| 隆德县| 呈贡县| 宣威市| 忻州市| 尼玛县| 汤原县| 鄂尔多斯市| 泉州市| 临猗县| 阳城县| 莱阳市| 新乡县| 江孜县| 贵定县| 临汾市| 南汇区| 沾化县| 崇左市| 陆良县| 十堰市| 江北区| 平乐县| 南岸区| 资溪县| 罗平县| 桦甸市| 浦县| 平陆县| 吴忠市| 北流市| 庆元县| 松原市| 玉林市| 肃北| 西充县| 博野县| 西吉县| 东光县| 隆化县| 承德市|