python--装饰器(附偏函数、断言)
博客地址:http://www.cnblogs.com/yudanqu/
?
概念:裝飾器是一個閉包,把一個函數(shù)當(dāng)做參數(shù)返回一個替代版的函數(shù),本質(zhì)上就是一個返回函數(shù)的函數(shù)
?
裝飾器就是在我們需要的一個函數(shù)外面包裝一個外殼,當(dāng)我們希望這個函數(shù)更漂亮?xí)r,可以通過改變這個包裝的樣子即可,而不需要更改原函數(shù),也可以避免出錯。
1、簡單的裝飾器
def func2(func):def inner():print('************')func()return innerdef func1():print("this is one")f = func2(func1) f()下面我解釋一下這個裝飾器,可以看到,func1是我們真正需要的函數(shù),這時候我們想在輸出這個函數(shù)時再多添加一些功能,那么我們就需要對func1這個函數(shù)進行裝飾。func2是一個外部的輸出函數(shù),他的參數(shù)是func,這只是個形參,使用的時候?qū)⑿枰b飾的函數(shù)傳入即可,當(dāng)我們執(zhí)行func2這個函數(shù)的時候,其內(nèi)部還有一個函數(shù)inner(),但是里面inner只是創(chuàng)建了這個函數(shù)而沒有被調(diào)用(這個大家能理解嗎,就是我們在定義一個函數(shù)時,他不會自動被調(diào)用,我們使用他時需要人為的通過這個函數(shù)來調(diào)用一下)內(nèi)部讀取代碼僅讀到def inner()這里并不進去,繼續(xù)向下就到了return inner,這里返回了內(nèi)部的那個函數(shù)名,但也只是個名字沒有被調(diào)用(函數(shù)名后面加上小括號才可以調(diào)用)。那么return返回給誰呢,就給了下面的f,用f來接收func2的return值,現(xiàn)在f就是return的inner。進行最后一步,調(diào)用inner,上一步我們已經(jīng)知道f就是inner,調(diào)用他就加個小括號就可以了。調(diào)用了inner函數(shù)后,他的內(nèi)部有func()這個函數(shù),并且調(diào)用了,所以可以直接執(zhí)行func內(nèi)的語句塊。func就是最外面?zhèn)鬟M來的參數(shù),也就是我們需要被裝飾的函數(shù)。小伙伴們慢慢理一下思路,一定要把第一個理清楚了,那么后面就輕而易舉了。
2、裝飾器進階(含有一個參數(shù))
def func4(func):def inner(age):if age < 0:age = 0func(age)return innerdef func3(age): print("this is two %d" % age)f = func4(func3)f(-7)看一下,這個框架和第一個幾乎一樣對吧,唯獨多了一個參數(shù),這個參數(shù)是最后由我們裝飾的那個函數(shù)來使用,由最外部傳入。我們把參數(shù)給在了inner函數(shù),這是為什么呢?我們想一下,我們裝飾的函數(shù)是在什么時候調(diào)用的,是不是在調(diào)用了inner函數(shù)后,inner函數(shù)內(nèi)自動調(diào)用的啊。那么在調(diào)用inner函數(shù)時才調(diào)用的目標函數(shù),我們不就應(yīng)該把目標函數(shù)的參數(shù)從這里傳進去嗎(最外層的函數(shù)是個包裝的作用,他是為了返回inner函數(shù)的地址,來為之后調(diào)用inner做準備),我們在用f接收這個inner函數(shù),我們調(diào)用他還需要加個小括號f(),這才是調(diào)用inner,既然這里調(diào)用,正好有個傳入?yún)?shù)的接口,我們趁著這個機會把想要實現(xiàn)的func3函數(shù)的參數(shù)扔進去,豈不美哉,接下來我們執(zhí)行func3函數(shù)的時候,只需要把上面接收到的參數(shù)再傳到自己的接口里就好了。
22、改進
@func4 def func3(age):print("this is two %d" % age) # 這時就可以直接使用原來的func3函數(shù)了,不需要引入變量來接收,就已經(jīng)可以使用裝飾器里的內(nèi)容 func3(-7)@符號是裝飾器的語法糖,在定義函數(shù)時,可以避免賦值操作
那么這段代碼有什么作用呢?
其實他可以替換掉上方代碼的后四行,代碼中最開始的裝飾器是一樣的,我們改進在使用裝飾器上。上面我們通過先定義一個目標函數(shù),然后把他作為參數(shù)傳入裝飾器里,然后用一個變量f來接收,最終調(diào)用f()來實現(xiàn)裝飾作用,這樣是不是繁瑣了點呢,我們做了這么多工作,而且可能會把我們搞暈,其中還引入了變量,當(dāng)代碼很長時,那么多的變量我們怎么記得住呢。這時就有了語法糖。大約在python2.4就開始可以使用@符號了。也許大家見過,有時候會有@staticmethod,@classmethod的字眼,這就是python的內(nèi)置裝飾器。
@func4的作用就是替代了上方在裝飾器里傳參數(shù)然后賦值的過程,可以理解為通過這樣一個符號,就已經(jīng)把自己變成裝飾了之后的樣子,那么我們再使用的時候,只需要和以往一樣,調(diào)用函數(shù),傳參就可以了。當(dāng)然是不是真正的變了,當(dāng)下方再次使用這個函數(shù)時,如果不添加語法糖還會是函數(shù)自己。
?
但此時的裝飾器只能接收一個參數(shù),為整形,因為內(nèi)部使用了判斷,這樣的話我們很多事情就不是很方便了,使用裝飾器就是方便我們進行后續(xù)的操作,這樣的話我們使用不一樣的功能還得總是修改裝飾器。那么,我們繼續(xù)向下看。
3、進進階裝飾器(通用裝飾器)
def func5(func):def inner(*args,**kwargs):# 功能print("&&&&&&")func(*args,**kwargs)return inner@func5 def func6(name,age,gender=1,number='00000000'):print('%s is %d years old,number is %s,gender:%d' % (name,age,number,gender)) func6('張三',18,0,'05162002')# 函數(shù)的參數(shù)理論上是無限制的,但實際上最好不要超過6到7個這個其實沒有太多要說的,只是把參數(shù)換成了不定長參數(shù)
*args:可以接受不限量個參數(shù),將他們打包成tuple給函數(shù)
**kwargs:可以將關(guān)鍵字參數(shù)打包成字典給函數(shù)
有了上面兩個,那么幾乎所有的參數(shù)都可以隨便輸入了。
4、最后再順帶說一下偏函數(shù)和斷言,但這個不是重點:
1 ''' 2 我理解為偏函數(shù)就是可以通過控制參數(shù)來實現(xiàn)功能 3 ''' 4 5 # 這樣的一個功能,接下來實現(xiàn)它 6 print(int('1010', base = 2)) 7 # base = 2 意思是把字符串當(dāng)做二進制來計算,就是把這個字符串以二進制來判斷他是多少,以十進制輸出 8 9 # 第一種方法 10 def int2(str, base = 2): # 表示設(shè)置默認值為2.將來用base值來轉(zhuǎn)換 11 return int(str, base) 12 13 # 第二種方法(偏函數(shù)) 14 import functools # 這個模塊幫我們定義偏函數(shù) 15 int2 = functools.partial(int, base = 2) 1 ''' 2 斷言 3 ''' 4 5 def func(num, div): 6 assert (div != 0), "div不能為0" # 斷言 7 return num/div 8 9 func(10, 0) 10 # 函數(shù)本身分母不為零,如果為零那么將報錯,使用斷言,當(dāng)沒有錯誤時不產(chǎn)生效果,當(dāng)有錯誤時會告訴你哪里錯了?
?
作者:漁單渠(yudanqu)
博客地址:http://www.cnblogs.com/yudanqu/
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/yudanqu/p/9091826.html
總結(jié)
以上是生活随笔為你收集整理的python--装饰器(附偏函数、断言)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 迅为I.MX6Q开发板配不同分辨率不同尺
- 下一篇: python多线程不能利用多核cpu,但