日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

python 自定義裝飾器實(shí)例詳解

系統(tǒng) 1685 0

本文實(shí)例講述了python 自定義裝飾器。分享給大家供大家參考,具體如下:

先看一個(gè)例子

            
def deco(func):
  print("before myfunc() called.")
  func()
  print("after myfunc() called.")
  return func
@deco
def myfunc():
  print("myfunc() called.")
# myfunc = deco(myfunc) # 與上面的@deco等價(jià)
myfunc()
print("***********")
myfunc()


          

會(huì)發(fā)現(xiàn),輸出為

before myfunc() called.
myfunc() called.
after myfunc() called.
myfunc() called.
***********
myfunc() called.

這就是說(shuō),裝飾器里面的東西只調(diào)用了一次,為什么呢?

是因?yàn)椋趍yfunc()函數(shù)的定義前面加一句@deco, 本質(zhì)上完全等價(jià)于在出現(xiàn)def myfunc()后,先將下面所有內(nèi)容的首地址傳遞給func,然后緊接著加上一句 myfunc = deco(myfunc)。 執(zhí)行這句話,表示func代表了本來(lái)定義的myfunc()的函數(shù)體,同時(shí)函數(shù)myfunc()的地址傳遞給deco()函數(shù),即 myfunc -> func,這里就相當(dāng)于myfunc的值與func的值完全相同了。然后執(zhí)行裝飾器里面的內(nèi)容,最后返回給func,傳遞給myfunc。接下來(lái)在調(diào)用myfunc()的時(shí)候,打印輸出“myfunc() called”。第二次調(diào)用myfunc()函數(shù)的時(shí)候,依然只打印輸出“myfunc() called”。為什么第二次沒(méi)有執(zhí)行裝飾器里面的內(nèi)容呢?是因?yàn)椋琺yfunc = deco(myfunc)這句話只執(zhí)行了一次,而這句話,才是真正執(zhí)行裝飾器里面的內(nèi)容的話。

上面的代碼表示,裝飾器相當(dāng)于只對(duì)第一次調(diào)用他的函數(shù)進(jìn)行了裝飾,那么,怎么對(duì)每次調(diào)用的函數(shù)都裝飾呢?接著看

            
def deco(func):
  def wrapper(*args, **kwargs): # *args, **kwargs用于接收f(shuō)unc的參數(shù)
    print("before myfunc() called.")
    func(*args, **kwargs)
    print("after myfunc() called.")
  return wrapper
@deco
def myfunc(a, b):
  print(a+b)
# myfunc = deco(myfunc) # 與上面的@deco等價(jià)
myfunc(1, 2)
print("***********")
myfunc(3, 4)


          

該代碼輸出結(jié)果為

before myfunc() called.
3
after myfunc() called.
***********
before myfunc() called.
7
after myfunc() called.

我們說(shuō)了,在myfunc()函數(shù)的定義前面加一句@deco, 本質(zhì)上完全等價(jià)于在出現(xiàn)def?myfunc()后,先將下面所有內(nèi)容的首地址傳遞給func,然后緊接著加上一句 myfunc = deco(myfunc)。 執(zhí)行myfunc(1, 2)命令的時(shí)候,myfunc函數(shù)體的地址早已經(jīng)傳遞給了deco()函數(shù),返回的是wrapper。這是myfunc所代表的地址不再是原來(lái)的myfunc的地址,而是wrapper函數(shù)的地址。所以,以后凡是出現(xiàn)myfunc()的地方,都是在調(diào)用wrapper()函數(shù)。即myfunc(1, 2)就是wrapper(1, 2),所以每次調(diào)用myfunc()時(shí)候,裝飾器里面的內(nèi)容都會(huì)被執(zhí)行了。而wrapper()函數(shù)體里面的func,就代表了原來(lái)myfunc()的函數(shù)體。

怎么進(jìn)一步理解“ 在出現(xiàn)def?myfunc()后,先將下面所有內(nèi)容的首地址傳遞給func ”這句話呢?看:

            
def deco(func):
  def wrapper(*args, **kwargs): # *args, **kwargs用于接收f(shuō)unc的參數(shù)
    print("wrapper的地址:", wrapper)
    func(*args, **kwargs)
    print("func的地址:", func)
  return wrapper
@deco
def myfunc(a, b):
  print("myfunc的地址:",myfunc)
  print(a+b)
# myfunc = deco(myfunc) # 與上面的@deco等價(jià)
myfunc(1, 2)
print("***********")
print("修改后myfunc的地址:",myfunc)


          

運(yùn)行結(jié)果:

wrapper的地址: .wrapper at 0x0000023AA9FF58C8>
myfunc的地址: .wrapper at 0x0000023AA9FF58C8>
3
func的地址:
***********
修改后myfunc的地址: .wrapper at 0x0000023AA9FF58C8>

程序執(zhí)行到myfunc(1,2)的時(shí)候,本質(zhì)上是在執(zhí)行wrapper(1, 2),于是先輸出wrapper的地址,再執(zhí)行func()函數(shù)。執(zhí)行func()函數(shù)的時(shí)候,輸出myfunc()的地址,(可見(jiàn),此時(shí)myfunc的值與wrapper的是相等),再打印3。當(dāng)輸出func()函數(shù)的地址,可見(jiàn)func()函數(shù)的地址與myfunc()函數(shù)的地址不一樣了!!!!這就是說(shuō),原來(lái)定義的myfunc()函數(shù)的函數(shù)體,已經(jīng)屬于func了,而不屬于myfunc了!!

進(jìn)一步見(jiàn)證奇跡!!

            
def deco(func):
  def wrapper(*args, **kwargs): # *args, **kwargs用于接收f(shuō)unc的參數(shù)
    pass
  return wrapper
@deco
def myfunc(a, b):
  print(a+b)
myfunc(1, 2)


          

該代碼沒(méi)有任何輸出。那是因?yàn)椋瑘?zhí)行myfunc(1, 2)的時(shí)候,本質(zhì)上是執(zhí)行wrapper(1, 2)。而wrapper(1, 2)又不干任何事情,所以沒(méi)有輸出。至于print(a+b)這句話,他的地址已經(jīng)屬于func了。

帶參數(shù)的裝飾器,可以參見(jiàn)其他文章

更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 永德县| 昆明市| 阆中市| 岳阳县| 武汉市| 宝应县| 荔波县| 保山市| 广河县| 连平县| 琼海市| 宁乡县| 宁夏| 新密市| 朔州市| 南京市| 长阳| 金门县| 新疆| 常山县| 廊坊市| 霍林郭勒市| 启东市| 四子王旗| 城固县| 渭源县| 齐齐哈尔市| 崇文区| 宜兰市| 通河县| 多伦县| 灵台县| 博白县| 富川| 广宁县| 龙海市| 稷山县| 东山县| 房产| 安丘市| 丹阳市|