python開發裝飾器的應用
阿新 • • 發佈:2018-03-29
urn 參數 username 什麽 alt 添加 file 回憶 h+
一、 裝飾器
裝飾器就是閉包函數的一種應用場景
什麽是閉包函數?我們再來回憶一下:
閉包函數:
定義在函數內部的函數,並且該函數包含對外部函數作用域(強調:對全局作用域名字的引用不算閉包)名字的引用,該函數稱為閉包函數
說到作用域我們再回憶下:
作用域:
全局範圍:內置+全局
全局有效,全局存活
局部範圍:局部
局部有效,局部存活
作用域關系是在函數定義階段就規定死,與調用位置無關,
也就是說,無論函數在哪兒調用,都必須回到當初定義函數時的位置找作用域關系
一 、為何要用裝飾器
#開放封閉原則: #軟件一旦上線後,就應該遵循開放封閉原則,對修改源代碼是封閉的,對功能的擴展是開放的,也就是我們必須找到一種解決方法: #能夠在不修改一個功能源代碼以及調用方式的前提下,為其加上新功能.
二 、什麽是裝飾器
#裝飾器他人的器具,本身可以是任意可調用對象,被裝飾者也可以是任意可調用對象。 #強調裝飾器的原則: #1 、不修改被裝飾對象的源代碼 #2 、不修改被裝飾對象的調用方式 #裝飾器的目標: #在遵循1和2的前提下,為被裝飾對象添加上新功能
三 、裝飾器的使用
#我們現在給下面函數增加一個運行時間的功能 import time def index(): time.sleep(3) print(‘welcome to index page‘) #修改一 def index(): start_time=time.time() time.sleep(3) print(‘welcome to index page‘) stop_time=time.time() print(‘run time is %s‘ %(stop_time-start_time)) index() #功能實現 #評語:直接改源代碼,這麽搞被開了。。。
#再來一位童靴,來實現功能 #修改二 import time def index(): time.sleep(1) print(‘welcome to index page‘) start_time=time.time() index() stop_time = time.time() print(‘run time is %s‘ % (stop_time - start_time)) #評語:有好多函數要實現這個功能,寫N遍變這個代碼, #後期維護一臉懵逼,還是被開。。。
#再來一位童靴,功能重復實現看我用強大的函數 #修訂三: import time def index(): time.sleep(3) print(‘welcome to index page‘) def wrapper(func): #func=index start_time=time.time() func() #index() stop_time = time.time() print(‘run time is %s‘ % (stop_time - start_time)) wrapper(index) #評語:修改了原函數的調用方式,依然被開。。。
#終於來了位小牛的童靴,函數的值可以返回,然後我再把重新定義index #修訂四: import time def index(): time.sleep(3) print(‘welcome to index page‘) def outter(func): #func=最原始的index # func=最原始的index def wrapper(): start_time=time.time() func() stop_time=time.time() print(stop_time-start_time) return wrapper index=outter(index) # 新的index=wrapper index() #wrapper() 功能基本實現 #評語:在原值沒有返回值是沒問題,但是有返回值的情況下,這麽搞就會發現返回的是None
#這次小牛牛童靴路過看到這情況,say這麽搞! #修訂五 import time def index(): time.sleep(1) print(‘welcome to index page‘) return 123 #假使這裏返回123 返回值可以是任意類型 #==============下面就是裝飾器 def timmer(func): #func=最原始的index def wrapper(*args,**kwargs): #可變長參數 start_time=time.time() res=func(*args,**kwargs) #調用最原始的index stop_time=time.time() print(stop_time-start_time) return res #index()運行的返回值 return wrapper index=timmer(index) # 新的index=wrapper print(index()) #功能已經實現,返回值123 #評語:這裏的裝飾的功能已經實現,返回的值也得到,小牛牛不是白叫的
#天上五彩紅光,大牛童靴出現!各位童靴火速圍觀! import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-start_time) return res return wrapper @timmer #index=timmer(index) 裝飾器的標準格式! def index(): time.sleep(1) print(‘welcome to index page‘) return 123 @timmer # home=timmer(home) def home(name): time.sleep(2) print(‘welcome %s to home page‘ %name) # index() #home(‘egon‘) #評語:大牛就是大牛!大牛say:教你們絕技,不會的童靴可以照下面的模板實現: #無參裝飾器模板 def outer(func): #outer,inner名字功能隨意 def inner(*args,**kwargs): res=func(*args,**kwargs) return res return inner @outer #裝飾器要在裝飾函數的上方 def duoduo(): pass
四 、裝飾器語法
#被裝飾函數的正上方,單獨一行 @deco1 @deco2 @deco3 def foo(): pass #foo=deco1(deco2(deco3(foo))) #這裏的思想就是最上面裝飾器,裝飾的下面所有的函數(deco2,deco3,foo) #然後deco2裝飾(deco3,foo),最後deco3裝飾foo #功能的不同,放的順序也要註意,不然裝飾的效果可能實現的就不對了!
五、多個裝飾器的使用:
import time current_user={ ‘username‘:None, # ‘login_time‘:None } def auth(func): # func=index def wrapper(*args,**kwargs): if current_user[‘username‘]: #這裏是認證過的,下次就不用認證 print(‘已經登陸過了‘) res=func(*args,**kwargs) return res uname=input(‘用戶名>>: ‘).strip() pwd=input(‘密碼>>: ‘).strip() if uname == ‘egon‘ and pwd == ‘123‘: print(‘登陸成功‘) current_user[‘username‘]=uname res=func(*args,**kwargs) return res else: print(‘用戶名或密碼錯誤‘) return wrapper def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(stop_time-start_time) return res return wrapper @timmer # timmer 統計的是auth+index的執行時間 @auth #我們只裝飾index的話就要把@timmer緊跟index def index(): time.sleep(1) print(‘welcome to index page‘) return 123 @auth @timmer #這裏統計的就是home運行的時間 def home(name): time.sleep(2) print(‘welcome %s to home page‘ %name) #index() #home("duoduo")
六、有參數的裝飾器的使用:
import time current_user={ ‘username‘:None, # ‘login_time‘:None } def auth(engine): #道理還是那個道理,在外面包了一層engine的值 # engine=‘file‘ #這個值外面穿什麽進來就是什麽 def auth2(func): # func=index def wrapper(*args,**kwargs): if engine == ‘file‘: if current_user[‘username‘]: print(‘已經登陸過了‘) res=func(*args,**kwargs) return res uname=input(‘用戶名>>: ‘).strip() pwd=input(‘密碼>>: ‘).strip() if uname == ‘egon‘ and pwd == ‘123‘: print(‘登陸成功‘) current_user[‘username‘]=uname res=func(*args,**kwargs) return res else: print(‘用戶名或密碼錯誤‘) elif engine == ‘mysql‘: #engine 值得判斷情況 print(‘基於MyQL的認證‘) elif engine == ‘ldap‘: print(‘基於LDAP的認證‘) return wrapper return auth2 #這裏也要返回auth2的內存地址 @auth(‘ldap‘) #@auth2 #index=auth2(index) #index=wrapper def index(): time.sleep(1) print(‘welcome to index page‘) return 123 index() # wrapper()
python開發裝飾器的應用