日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Python學習筆記之裝飾器

瀏覽:171日期:2022-07-14 18:10:15

一. 什么是裝飾器

知乎某大佬如是說:內褲可以用來遮羞,但是到了冬天它沒法為我們防風御寒,聰明的人們發明了長褲,有了長褲后寶寶再也不冷了,裝飾器就像我們這里說的長褲,在不影響內褲作用的前提下,給我們的身子提供了保暖的功效。裝飾器本質上是Python函數,可以為已存在的對象添加額外的功能,同時裝飾器還可以抽離出與函數無關的重用代碼。具體應用場景如:插入日志、性能測試、事務處理、緩存、權限校驗等。

換言之

裝飾器不能影響原函數的功能,裝飾器是獨立出來的函數。誰調用它,誰就可以使用它的功能。

二.舉個栗子

add的功能是計算x和y的值,我們稱作功能函數。logger的作業是在執行add函數的同時再打印了其他的信息,這部分的作為add的功能增強,我們稱為裝飾。在logger里我們可以加入其他類似的功能函數,也能包裝它,可以進行復用。

1.引子

#功能函數def add(x,y): return x+y#裝飾函數def logger(fn): print(’frist’) x = fn(4,5) print(’second’) return x print(logger(add))#把函數add傳給logger ,return x+y#print(’frist’)#print(’secend’)# x = fn(4,5) ==> x = 4 y= 5 x= 4+5 = 9 #return 9

fristsecond9

2.提取參數

x,y的參數都放在logger函數內部了,影響函數的靈活性,此處我們可以提取出來。

def add(x,y): return x + ydef logger(fn,*args,**kwargs): print(’frist’) x = fn(*args,**kwargs) print(’second’) return xprint(logger(add,1,y=11))

fristsecond12

3.柯里化

def add(x,y): return x + ydef logger(fn): def wrapper(*args,**kwargs): print(’begin’) x = fn(*args,**kwargs) print(’end’) return x return wrapperprint(logger(add)(5,y=11))

beginend16

懵逼ing

以下為個人理解,左邊為非柯里化函數,右邊是柯里化函數。

Python學習筆記之裝飾器

柯里化函數

前面說過柯里化的定義,本來可以一次傳入兩個參數,柯里化之后。只需要傳入一個函數了。。左邊傳入add 和 兩個參數。右邊的logger(add)是一個函數,只需要傳入兩個參數。logger(add)是個整體,結合成一個函數。當然這樣寫,我們看函數主題的部分也是不一樣的。函數的基礎中說過,函數的傳參必須和函數參數的定義一致。重點分析右邊函數(柯里化)。參數部分:參數傳入的方式,logger函數需要傳入個fn,fu的返回值是wrapper函數,wrapper函數的參數是(*args,**kwargs)所以此次就需要分兩次傳入參數。第一次傳入fn,再次傳入wrapper函數需要的參數。所以就出現了最下邊的調用方式。print(logger(add)(5,y=50))。

返回值部分:右側的logger函數是個嵌套函數,logger的返回值是wrapper,內層的wrapper函數返回值是x,x = fn(*args,**kwargs)。fn函數是最后調用時候傳入的add函數。

懵逼 X 2。。。。

def add(x,y): return x + ydef logger(fn,*args,**kwargs): def logger(fn): #參數剝離 def newfunction(*args,**kwargs): #新定義一個函數,logger函數返回也是這個函數名字 print(’frist’) print(’frist’) x = fn(*args,**kwargs) == > x = fn(*args,**kwargs) print(’second’) print(’second’) return xreturn x return newfunctionprint(logger(add,1,y=11)) print(logger(add)(5,y=11)) #兩次傳入參數

效果如下:

def add(x,y): return x + ydef logger(fn): #參數剝離 def newfunction(*args,**kwargs): #新定義一個函數,logger函數返回也是這個函數名字 print(’frist’) x = fn(*args,**kwargs) print(’second’) return x return newfunctionprint(logger(add)(5,y=11)) #兩次傳入參數

fristsecond16

繼續懵逼的話就這樣用吧。。。用多了就悟道了。。

4.裝飾器語法糖

#再次變形。。。def add(x,y): return x + ydef logger(fn): def wrapper(*args,**kwargs): print(’begin’) x = fn(*args,**kwargs) print(’end’) return x return wrapper##調用方法1:print(logger(add)(x=1111,y=1))##調用方法2:add = logger(add)print(add(x=11,y=3))##調用方法3: python給我們的語法糖 @logger # 說明下邊的函數,add 其實是 add = logger(add)def add(x,y): return x + yprint(add(45,40))

beginend1112beginend14beginend85

三.復雜的栗子

import datetimeimport time def logger(fn): def warp(*arges,**kwarges): print('arges={},kwarges={}'.format(arges,kwarges)) #打印函數的兩個參數 start = datetime.datetime.now() #獲取函數運行的開始時間 ret = fn(*arges,**kwarges) #傳入兩個參數,調用add函數 此處有個return的值,需要一層一層的返回出去 duratime = datetime.datetime.now() - start #獲得函數的運行時間 print('function {} took {}s'.format(fn.__name__,duratime.total_seconds())) #打印函數的運行時間 return ret #返回fn的結果 ,fn = x+y ==> 返回x+y的值。 x = 4 y= 11 ==> return 11 return warp #返回warp的 return ==> ret 的return ==> return 11 函數的最終結果為11 @loggerdef add(x,y): print('oooooook') time.sleep(1.5) return x+yprint(add(4,y=11))#如果充分理解了每個小部件,這個簡單的完整版本也是很好理解的了。#1,logger是個裝飾器,而且使用了柯里化技術#2,add 傳參給logger的fn 形參,add(4,y=5)的兩個參數傳入給warp函數的兩個形參##

arges=(4,),kwarges={’y’: 11}oooooookfunction add took 1.5017s15

再次翻譯

import datetimeimport time #####################################裝飾開始############################################def logger(fn): #拿到函數名稱 def warp(*arges,**kwarges): #拿到函數帶過來的參數開始裝飾 print('arges={},kwarges={}'.format(arges,kwarges)) #來試試打印兩個參數 start = datetime.datetime.now() # ret = fn(*arges,**kwarges) # 此處調用add函數。開始執行函數,發現return語句。。ret的結果就是return。 duratime = datetime.datetime.now() - start # print('function {} took {}s'.format(fn.__name__,duratime.total_seconds())) return ret #加工完成開始返回。warp的返回值是ret ,ret的返回值是 add函數的執行結果(原函數的功能完整的保留了) return warp # logger的返回結果是warp,warp的返回值是ret ,ret的返回值是 add函數的執行結果(原函數的功能完整的保留了) #####################################裝飾完成############################################@logger #裝飾工廠######add是需要被裝飾的函數,當你有這個想法的事情,其實事情已經開始發生了。def add(x,y): # 此時add = logger(add) 此處前面的@logger標記就是想要讓logger裝飾器像一個工廠一樣對add函數進行加工。 print('oooooook') time.sleep(1.5) return x+yprint(add(4,y=11))

arges=(4,),kwarges={’y’: 11}oooooookfunction add took 1.501604s15

四.帶參裝飾器

1. 文檔字符串

我們約定,在python函數的第一行需要對函數進行說明,使用三引號表示。如果是英文說明,慣例首字母大寫,第一行寫概述,空一行,第三行寫詳細描述。如果函數中有文檔字符串,默認會放在函數的doc屬性中,可以直接訪問。

def add(x,y): '''This is a function of addition''' a = x+y return x + yprint('function name is {}function doc = {}'.format(add.__name__, add.__doc__))print(help(add))function name is addfunction doc = This is a function of additionHelp on function add in module __main__:add(x, y) This is a function of additionNone

2. 前面裝飾器的副作用

前面裝飾器基本上已經可以完成對函數進行加強的功能了,但是還有些瑕疵。比如原來函數的原屬性已經被替換為裝飾器的屬性了。如下:

def add(x,y): return x + ydef logger(fn): 'This is logger doc' def wrapper(*args,**kwargs): 'This is wrapper doc' print(’begin’) x = fn(*args,**kwargs) print(’end’) return x return wrapper@logger # add = logger(add)def add(x,y): 'This is add doc ' print('name = {}doc = {}'.format(add.__name__,add.__doc__)) return x + yprint(add(45,40))#可以看出來add被裝飾出來的函數(新的add)的屬性已經全部改變了。

beginname = wrapperdoc = This is wrapper docend85

3. 解決方案一

三個函數:

第一個:copy原函數的屬性 copy_properties第二個:裝飾器 logger第三個:功能函數 add

def copy_properties(src, dst): # 把src的相關屬性賦值給dst (fn,wrap) dst.__name__ = src.__name__ dst.__doc__ = src.__doc__def logger(fn): '''’This is a function of logger’''' def wrap(*arges,**kwarges): # '''’This is a function of wrap’''' print(’<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>’) x = fn(*arges,**kwarges) #print('name={}doc={}'.format(add.__name__,add.__doc__)) print(’<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>’) return x copy_properties(fn,wrap) #思考1:為什么放在這個位置調用 return wrap@loggerdef add(x,y): '''’This is a function of add’''' print('name={}doc={}'.format(add.__name__,add.__doc__)) return x+yprint(add(4,6))

<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>name=adddoc=’This is a function of add’<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>-<>10

4. 解決方案二

但凡使用裝飾器都會出現屬性的這個問題,為什么不把copy_properties也做成裝飾器呢?

三個函數:

第一個:copy原函數的裝飾器 copy_properties1第二個:裝飾器 logger第三個:功能函數 add

def copy_properties(src, dst): # 把src的相關屬性賦值給dst (fn,wrap) dst.__name__ = src.__name__ dst.__doc__ = src.__doc__#利用前面的知識我們可以對copy_properties輕松進行變形def copy_properties1(src): # 把src的相關屬性賦值給dst (fn,wrap) def _copy(dst): dst.__name__ = src.__name__ dst.__doc__ = src.__doc__ return dst return _copy

帶參裝飾器:

def logger(fn): '''’This is a function of logger’''' @copy_properties1(fn) #wrap = copy_properties(fn)(wrap) #== > 柯里化 兩次傳入參數 src = fn , dst = wrap 新的wrap函數的屬性已經替換為原函數的。 def wrap(*arges,**kwarges): #wrap = copy_properties(fn)(wrap)(*arges,**kwarges) '''’This is a function of wrap’''' print(’>->->->->->->->->->->->->->->->->->->->->->->->->->’) x = fn(*arges,**kwarges) print(’<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<’) return x return wrap@logger #add =logger(add)def add(x,y): '''’This is a function of add’''' print('name={}doc={}'.format(add.__name__,add.__doc__)) return x+yprint(add(4,11))

以上就是詳解Python 裝飾器的詳細內容,更多關于Python 裝飾器的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品欧美视频| 国产精品magnet| 99久久精品费精品国产| 日韩国产欧美在线播放| 国产视频一区二| 国产成人1区| 久久中文字幕一区二区| 成人亚洲一区| 日韩大片在线| 鲁大师成人一区二区三区| 中文字幕日韩欧美精品高清在线| 免费视频久久| 国产精品色婷婷在线观看| 手机精品视频在线观看| 国产精东传媒成人av电影| 日韩一区二区三区精品| 今天的高清视频免费播放成人| 亚洲资源av| 国产一区二区三区四区五区传媒| 欧美激情视频一区二区三区免费 | 久久婷婷久久| 亚洲激情二区| 欧美激情日韩| 国内精品99| 国产精品一区二区精品视频观看 | 亚洲欧美日韩国产| 国产日本精品| 在线亚洲成人| 欧美欧美黄在线二区| 日韩av资源网| 久久一区国产| 精品国产黄a∨片高清在线| av高清不卡| 亚洲欧美日本国产| 欧美aaaaaa午夜精品| 欧美三区四区| 神马日本精品| 国产精品久久久一区二区| 日韩av一区二区三区| 悠悠资源网久久精品| 不卡av一区二区| 午夜视频一区二区在线观看| 国产视频一区免费看| 视频在线不卡免费观看| 中文字幕人成乱码在线观看| 国产一区二区三区探花| 国产高潮在线| 伊人久久大香伊蕉在人线观看热v| 国产精品久久乐| 日韩视频免费| 蜜桃久久久久| 99国产精品私拍| 国产视频一区二区在线播放| 久久精品动漫| 久久久久九九精品影院| 亚洲ww精品| 中文无码日韩欧| 狠狠爱成人网| av资源亚洲| 久久99青青| 亚洲精品自拍| 亚洲婷婷免费| 理论片午夜视频在线观看| 国产毛片久久久| 亚洲免费福利一区| 免费欧美在线视频| 欧美在线观看天堂一区二区三区| 里番精品3d一二三区| 欧美日韩夜夜| 日本在线视频一区二区| 国产精品免费看| 夜久久久久久| 中文一区二区| 久久高清免费观看| 天堂va欧美ⅴa亚洲va一国产| 婷婷亚洲成人| 一区福利视频| 亚洲日本网址| 伊人精品一区| 美女被久久久| 青青国产91久久久久久| 久久精品 人人爱| 亚洲精品日本| 91欧美精品| 国产成人免费精品| 久久三级视频| 免费成人在线影院| 国产无遮挡裸体免费久久 | 快she精品国产999| 久久av一区二区三区| 婷婷精品在线| 国产精品v日韩精品v欧美精品网站 | 欧美影院视频| 久久丁香四色| 免费毛片在线不卡| 久久国际精品| 成人亚洲一区二区| 日韩在线卡一卡二| 国产精品美女午夜爽爽| 日韩精品久久久久久久电影99爱 | 欧美一区精品| 久久亚洲资源中文字| 久久久久亚洲| 性欧美xxxx免费岛国不卡电影| 亚洲少妇诱惑| 精品一区av| 视频在线观看91| 久久狠狠久久| 欧美综合国产| 欧美日韩免费看片| 青青草国产成人99久久| 尹人成人综合网| caoporn视频在线| 日韩欧美2区| 五月综合激情| 波多野结衣久久精品| 欧美一区二区三区久久精品| 伊人久久大香线蕉av不卡| 国产精久久久| 日韩精品视频在线看| 国产中文一区| 国产理论在线| 日韩中文av| 欧美中文日韩| 国产亚洲激情| 日韩午夜av| 99精品美女| 精品不卡一区| 久久99影视| 国产精品v日韩精品v欧美精品网站 | 精品国产亚洲一区二区在线观看| 免费成人在线视频观看| 尹人成人综合网| 一本一道久久a久久精品蜜桃| 欧美成人a交片免费看| аⅴ资源天堂资源库在线| 麻豆国产91在线播放| 国产精品v一区二区三区| 日本欧美韩国一区三区| 日本99精品| 久久亚洲人体| av高清不卡| 9色精品在线| 蜜臀国产一区二区三区在线播放| 日韩视频一区| 亚洲一区区二区| 日韩欧美中文字幕电影| 日本午夜精品视频在线观看| 国产欧美另类| 日产精品一区二区| 亚洲天堂一区二区| 黑丝一区二区| 日韩精品免费观看视频| 国产精品激情电影| 精品香蕉视频| 欧美女激情福利| 日韩高清三区| 欧美www视频在线观看| 国产精品88久久久久久| 亚洲资源在线| 日韩黄色在线观看| 电影亚洲精品噜噜在线观看| 99国产精品久久久久久久| 91嫩草精品| 久久一区二区三区电影| 在线看片一区| 蜜桃av在线播放| 日韩中文字幕av电影| 久久av超碰| 视频一区视频二区中文| 精品一区二区三区的国产在线观看| 91精品蜜臀一区二区三区在线| 少妇精品在线| 亚洲电影在线| 精品久久美女| 模特精品在线| 麻豆mv在线观看| 日韩视频1区| av亚洲在线观看| 福利欧美精品在线| 欧美日韩伊人| 免费在线欧美视频| 国产一区日韩欧美| 欧美男人天堂| 国产一区二区三区四区大秀| 综合色一区二区| 日韩精品一区第一页| 久久人人精品| 天堂а√在线最新版中文在线| 国产精一区二区| 在线亚洲成人| 91精品91| 性欧美xxxx免费岛国不卡电影| 麻豆国产精品视频| 国产区精品区| 欧美国产精品| www.com.cn成人| 国产字幕视频一区二区| 久久香蕉国产| 欧美日韩视频|