裝飾器做用:裝飾器能夠在不改變函數體和函數調用的狀況下在該函數執行以前,或者執行以後進行額外的操做python
裝飾器功能:1.自動執行裝飾器函數並將其下面的函數名看成參數傳遞小程序
2.將裝飾器函數的返回值,賦值給被裝飾器函數app
def outer(func): def inner(): print('before') func() print('after') return inner @outer def f1(): print('F1'.center(10,'-')) f1()
執行結果:函數
before ----F1---- after
解析:spa
1.自動執行outer函數,並將下面的函數名f1看成參數傳遞code
2.將outer函數的返回值,從新賦值給f1,outer的返回值就是inner()函數體,而func() == 老f1(),blog
此時,新的f1()就是內存
print('before')utf-8
print('F1'.center(10,'-'))get
print('after')
def outer(func): def inner(): print('before') res = func()return res return inner @outer def f1(): return 'F1....' a = f1() print(a)
執行結果:
before
F1....
解析:
當函數有返回值時,一樣inner()方法就至關於f1(),也就是說inner()函數的返回值就是老f1()的返回值。inner()函數的返回值就是res,也就是老f1()的返回值。
dict_a = {'aa':123} str_a = 'abc' list_a = [1,2] def outer(func): def inner(*args,**kwargs): print('before') res = func(*args,**kwargs) return res return inner @outer def f1(*args,**kwargs): print(*args,**kwargs) return 'F1....' a = f1(str_a,list_a,dict_a) print(a)
執行結果:
before abc [1, 2] {'aa': 123} F1....
解析:
當被裝飾的函數有參數時,裝飾器函數的內層函數就至關於被裝飾的函數。f1()函數就至關於inner()函數,由於f1()在調用時有參數,因此須要在inner()函數增長參數,大多數狀況能夠寫成inner(*args,**kwargs)萬能參數的形式。
目前有一個小小的需求,寫一個小程序,要求用戶登陸後能夠查看home目錄,管理員能夠查看全部目錄,不登陸不能夠查看
代碼以下:
USER_INFO ={} def check_login(func): #驗證登陸裝飾器 def inner(*args,**kwargs): if USER_INFO.get('islogin',None): ret = func(*args,**kwargs) return ret else: print('請登陸') return inner def check_admin(func): #驗證admin裝飾器 def inner(*args,**kwargs): if USER_INFO.get('islogin',None): if USER_INFO.get('usertype',None) ==2: ret =func(*args,**kwargs) return ret else: print('無權查看') else: print('請登陸') return inner def login(): user = input('please input your name:') if user == 'admin': USER_INFO['islogin']=True USER_INFO['usertype']=2 else: USER_INFO['islogin']=True USER_INFO['usertype']=1 @check_login def home(): print('home') @check_admin def index(): print('index') def main(): while True: inp = input('1.login 2.home 3.index \n>>>') if inp == '1': login() elif inp =='2': home() elif inp == '3' : index() main()
執行結果:
1.login 2.home 3.index
>>>2
請登陸
1.login 2.home 3.index
>>>3
請登陸
1.login 2.home 3.index
>>>1
please input your name:xx #xx登陸
1.login 2.home 3.index
>>>2 #xx查看home目錄
home
1.login 2.home 3.index
>>>3
無權查看
1.login 2.home 3.index
>>>1
please input your name:admin #admin登陸
1.login 2.home 3.index
>>>2 #admin查看home目錄
home
1.login 2.home 3.index
>>>3 #admin查看index目錄
index
1.login 2.home 3.index
>>>
分析:這樣作雖然功能能夠實現,可是若是要是還有超級管理員或者其餘更高權限的用戶,還需寫更多的裝飾器,比較麻煩,代碼重用性過高
因此須要用多層裝飾器作權限驗證
代碼以下:
USER_INFO ={} def check_login(func): def inner(*args,**kwargs): if USER_INFO.get('islogin',None): #1 ret = func(*args,**kwargs) #2 return ret #7 else: print('請登陸') return inner def check_admin(func): def inner(*args,**kwargs): if USER_INFO.get('usertype',None) ==2: #3 ret =func(*args,**kwargs) #4 return ret #6 else: print('無權查看') return inner def login(): user = input('please input your name:') if user == 'admin': USER_INFO['islogin']=True USER_INFO['usertype']=2 else: USER_INFO['islogin']=True USER_INFO['usertype']=1 @check_login def home(): print('home') @check_login @check_admin def index(): #5 print('index') def main(): while True: inp = input('1.login 2.home 3.index \n>>>') if inp == '1': login() elif inp =='2': home() elif inp == '3' : index() main()
分析這段代碼:
def check_login(func): def inner(*args,**kwargs): if USER_INFO.get('islogin',None): #1 ret = func(*args,**kwargs) #2 return ret #7 else: print('請登陸') return inner def check_admin(func): def inner(*args,**kwargs): if USER_INFO.get('usertype',None) ==2: #3 ret =func(*args,**kwargs) #4 return ret #6 else: print('無權查看') return inner @check_login @check_admin def index(): #5 print('index')
首先,解釋器會先把check_login和check_admin這兩個函數加載到內存
而後先解釋@check_admin/def index(): 會把它們倆做爲一個總體去解釋,並定義爲new_index函數,其實就是check_admin裏的inner函數,index函數就是check_admin裏的func函數
此時,解釋器會繼續解釋@check_login/new_index 會把它們做爲一個總體去解釋,並定義爲new_new_index函數,其實就是check_login裏的inner函數,new_index函數就是check_login裏的func函數
此時,最外層函數就是new_new_index函數,也就是check_login裏的inner函數
解釋器從下往上解釋完後,會從上往下執行函數,先從check_login裏的inner函數執行
1.先執行 if USER_INFO.get('islogin',None): #1 ---》條件不知足直接print('請登陸')
2. ret = func(*args,**kwargs) #2
3. USER_INFO.get('usertype',None) ==2: #3 ---》條件不知足直接print('無權查看')
4. ret =func(*args,**kwargs) #4
5. def index(): #5
6. return ret #6
7. return ret #7
圖文分析:
#!/usr/bin/env python #coding:utf-8 def Before(request,kargs): print 'before' def After(request,kargs): print 'after' def Filter(before_func,after_func): def outer(main_func): def wrapper(request,kargs): before_result = before_func(request,kargs) if(before_result != None): return before_result; main_result = main_func(request,kargs) if(main_result != None): return main_result; after_result = after_func(request,kargs) if(after_result != None): return after_result; return wrapper return outer @Filter(Before, After) def Index(request,kargs): print 'index'