Python 基礎 裝飾器,python基礎裝飾器
今天把學過的裝飾器的知識進行回顧一下,說到裝飾器,第一反應就是這個東西呢就是用來裝逼的,為啥這樣說呢,是應為沒有這個東西照樣可以幹活,大部分工作都是可以做的,不管咋樣還是把學過的裝逼器梳理一下吧。
一、裝飾器是個什麼鬼?
裝飾的意思呢,就是修飾,裝點的意思可以給別的函數添加新的功能,器呢就是函數的意思,so 裝飾器即是為別的函數添加新的功能的函數。
二、作為一個裝飾器,他、它有什麼樣的規則呢?
1.不修改被裝飾函數的原始碼(開放封閉原則)
2.為被裝飾函數添加新功能後,不修改被修飾函數的調用方式
三、如何?一個裝飾器呢?
要實現一個可以使用的裝飾器就需要滿足:裝飾器=高階函數+函數嵌套+閉包
四、高階函數
上節介紹完了什麼是高階函數,只要滿足:1.函數可以接受函數名當參數進行傳遞 2.函數的傳回值可以返回一個函數名 只要能夠滿足上面的任何一條就認為構成的這個函數是高階函數
高階函數的例子:
def foo(): print('我的函數名作為參數傳給高階函數')def gao_jie1(func): print('我就是高階函數1,我接收的參數名是%s' %func) func()def gao_jie2(func): print('我就是高階函數2,我的傳回值是%s' %func) return funcgao_jie1(foo)gao_jie2(foo)
輸出的結果是:
我就是高階函數1,我接收的參數名是<function foo at 0x006896A8>
我的函數名作為參數傳給高階函數
我就是高階函數2,我的傳回值是<function foo at 0x006896A8>
#高階函數應用1:把函數當做參數傳給高階函數import timedef foo(): print('from the foo')def timmer(func): start_time=time.time() func() stop_time=time.time() print('函數%s 已耗用時間是%s' %(func,stop_time-start_time))timmer(foo)#總結:我們確實為函數foo增加了foo已耗用時間的功能,但是foo原來的執行方式是foo(),現在我們需要調用高階函數timmer(foo),改變了函數的調用方式把函數當做參數傳給高階函數
#高階函數應用2:把函數名當做參數傳給高階函數,高階函數直接返回函數名import timedef foo(): print('from the foo')def timmer(func): start_time=time.time() return func stop_time=time.time() print('函數%s 已耗用時間是%s' %(func,stop_time-start_time))foo=timmer(foo)foo()#總結:我們確實沒有改變foo的調用方式,但是我們也沒有為foo增加任何新功能函數傳回值是函數名
五、函數嵌套(就是函數中還有定義函數)
def father(name): print('from father %s' %name) def son(): print('from son') def grandson(): print('from grandson') grandson() son()father('還是牛')
六、閉包:(在一個範圍中放入的定義變數,就像打了一個包)
#閉包的概念:閉就是封裝的意思,就是把變數分裝起來;包:就是層的意思,與之前範圍意思是一樣的。#grandson中的變數有name(形式參數);son中的變數有grandson(函數名也是變數);father中的變數有:name(形式參數) sondef father(name): print('from the father %s' %(name)) def son(): print('from the son') def grandson(): print('from the grandson %s'%(name)) grandson() son()father('SB')
七、裝飾器的基本架構
def timmer(func): def wrapper(): print(func) func() return wrapperdef boo(): print('你就是個傻逼!')res = timmer(boo) # 返回的是wrapper的記憶體位址 <function timmer.<locals>.wrapper at 0x02129420>#print(res)res() #是在執行wrapper 函數
八、裝飾器的兩種形式:
第一種 無參數的裝飾器
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'},]current_user={'username':None,'login':False}def auth_deco(func): def wrapper(*args,**kwargs): if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('使用者名稱: ').strip() passwd=input('密碼: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('使用者名稱或者密碼錯誤,重新登入') return wrapper@auth_decodef index(): print('歡迎來到首頁面')@auth_decodef home(): print('這裡是你家')def shopping_car(): print('查看購物車啊親')def order(): print('查看訂單啊親')print(user_list)# index()print(user_list)home()
第二種 含有參數的裝飾器
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'},]current_user={'username':None,'login':False}def auth(auth_type='file'): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == 'file': if current_user['username'] and current_user['login']: res=func(*args,**kwargs) return res username=input('使用者名稱: ').strip() passwd=input('密碼: ').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd == user_dic['passwd']: current_user['username']=username current_user['login']=True res=func(*args,**kwargs) return res break else: print('使用者名稱或者密碼錯誤,重新登入') elif auth_type == 'ldap': print('巴拉巴拉小魔仙') res=func(*args,**kwargs) return res return wrapper return auth_deco#auth(auth_type='file')就是在運行一個函數,然後返回auth_deco,所以@auth(auth_type='file')#就相當於@auth_deco,只不過現在,我們的auth_deco作為一個閉包的應用,外層的包auth給它留了一個auth_type='file'參數@auth(auth_type='ldap')def index(): print('歡迎來到首頁面')@auth(auth_type='ldap')def home(): print('這裡是你家')def shopping_car(): print('查看購物車啊親')def order(): print('查看訂單啊親')# print(user_list)index()# print(user_list)home()