亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python 自定義裝飾器實例詳解

系統 1535 0

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

先看一個例子

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


          

會發現,輸出為

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

這就是說,裝飾器里面的東西只調用了一次,為什么呢?

是因為,在myfunc()函數的定義前面加一句@deco, 本質上完全等價于在出現def myfunc()后,先將下面所有內容的首地址傳遞給func,然后緊接著加上一句 myfunc = deco(myfunc)。 執行這句話,表示func代表了本來定義的myfunc()的函數體,同時函數myfunc()的地址傳遞給deco()函數,即 myfunc -> func,這里就相當于myfunc的值與func的值完全相同了。然后執行裝飾器里面的內容,最后返回給func,傳遞給myfunc。接下來在調用myfunc()的時候,打印輸出“myfunc() called”。第二次調用myfunc()函數的時候,依然只打印輸出“myfunc() called”。為什么第二次沒有執行裝飾器里面的內容呢?是因為,myfunc = deco(myfunc)這句話只執行了一次,而這句話,才是真正執行裝飾器里面的內容的話。

上面的代碼表示,裝飾器相當于只對第一次調用他的函數進行了裝飾,那么,怎么對每次調用的函數都裝飾呢?接著看

            
def deco(func):
  def wrapper(*args, **kwargs): # *args, **kwargs用于接收func的參數
    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等價
myfunc(1, 2)
print("***********")
myfunc(3, 4)


          

該代碼輸出結果為

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

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

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

            
def deco(func):
  def wrapper(*args, **kwargs): # *args, **kwargs用于接收func的參數
    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等價
myfunc(1, 2)
print("***********")
print("修改后myfunc的地址:",myfunc)


          

運行結果:

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

程序執行到myfunc(1,2)的時候,本質上是在執行wrapper(1, 2),于是先輸出wrapper的地址,再執行func()函數。執行func()函數的時候,輸出myfunc()的地址,(可見,此時myfunc的值與wrapper的是相等),再打印3。當輸出func()函數的地址,可見func()函數的地址與myfunc()函數的地址不一樣了!!!!這就是說,原來定義的myfunc()函數的函數體,已經屬于func了,而不屬于myfunc了!!

進一步見證奇跡!!

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


          

該代碼沒有任何輸出。那是因為,執行myfunc(1, 2)的時候,本質上是執行wrapper(1, 2)。而wrapper(1, 2)又不干任何事情,所以沒有輸出。至于print(a+b)這句話,他的地址已經屬于func了。

帶參數的裝飾器,可以參見其他文章

更多關于Python相關內容可查看本站專題:《Python數據結構與算法教程》、《Python Socket編程技巧總結》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》及《Python入門與進階經典教程》

希望本文所述對大家Python程序設計有所幫助。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产欧美日韩精品a在线观看高清 | 亚洲图片天堂 | 九色国产在视频线精品视频 | 日日摸夜夜添夜夜添毛片 | 久精品视频 | 99re视频精品全部免费 | 99在线视频精品费观看视 | 成人亚洲精品一区二区 | 免费看色片 | 人人爱天天做夜夜爽2020麻豆 | 奇米影视奇米四色888av | 精品久久国产视频 | 欧美亚洲一区二区三区四 | 亚洲欧美香蕉在线日韩精选 | 国产真实伦偷精品 | 综合一个色| 精品无人乱码一区二区三区 | 国产欧美日韩中文字幕 | 成人欧美一区在线视频在线观看 | 国产成人麻豆精品video | 国产一区二区在线不卡 | 亚洲系列中文字幕一区二区 | 国产精品免费看久久久 | 四虎影视亚洲精品 | 9999热| 九九免费精品视频 | 国产在线视频自拍 | 久久久久无码国产精品一区 | 视频一区二区三区在线 | 亚洲 国产 路线1路线2路线 | 狠狠插狠狠干 | 国产一国产一级毛片视频在线 | 毛色毛片免费看 | 精品中文字幕在线观看 | 综合色播| 黄色毛片毛茸茸 | 亚洲桃色视频 | 亚洲精品国产一区二区三 | 亚洲欧美日韩中文在线 | 国产真实伦视频在线观看 | 国产成人免费全部网站 |