1、裝飾器定義:
裝飾器本質上是一個 Python 函數或類,它可以讓其他函數或類在不需要做任何代碼修改的前提下增加額外功能,裝飾器的傳回值也是一個函數/類對象。
2、裝飾器的意義:
裝飾器的作用就是為已經存在的對象添加額外的功能。并且同時取出與函數功能不符的代碼到裝飾器中使之得到重用。
3、先來看一個最簡單的例子
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
user_statues = False # vip使用者登陸後改為True
def login(func):
def inner():
_user = 'cc' #假設調用了資料庫
_password = 's,123'
global user_statues #聲明全局變量
if user_statues == False:
user = input('使用者名:')
password = input('密碼:')
if _user == user and _password== password:
print('welcome %s login'%user)
user_statues = True
else:
print('Invalid user or password...')
else:
print('You haved allready login!')
if user_statues:
func() # 驗證通過了就調用相應功能
return inner #使用者調用login時,隻會傳回inner的記憶體位址,下次調用時再加上()才會執行inner函數
def home():
print('-----首頁-----')
def China():
print('----中國----')
def foreign():
print('----外國----')
China = login(China) # china = login(China) ,login調用被修飾函數的函數名(China)作為參數,然後再将傳回值賦給被修飾函數(China)
foreign = login(foreign)
China() # 使用者調用
foreign() # 使用者調用
注意:
軟體的開放-封閉原則
封閉:已實作的功能代碼不應該被修改
開放:對現有功能的擴充開放
可以看出裝飾器就是功能擴充專生的一般,專治各種不服,我既未修改原本的China函數,foreign()函數,又實作了認證登入。
China = login(China)可以替換為 @login,@login要發揮作用就得寫在緊貼所修飾的函數上方。
4、裝飾器進階版
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#傳參數普通版
user_status = False
def login(func):
def inner(*args,**kwargs):
_user = 'sc'
_pwd = 's,514'
global user_status
if user_status == False:
user = input('使用者名:')
pwd = input('密碼:')
if _user == user and _pwd== pwd:
print('Welocome %s login!'%user)
user_status = True
else:
print('Invalid username or password...')
else:
print('Ypu haved already login!')
if user_status:
func(*args,**kwargs) #無論是否傳參都行
return inner
def home():
print('-------首頁---------')
@login #jp = login(jp)
def jp(name):
print('------日本專區------',name)
home()
jp('宮崎駿')
5、裝飾器高階版
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
#微信、QQ更新版傳參
user_status = False
def login(auth_type): #QQ或微信登陸
def outer(func): # jp
def inner(*args,**kwargs):#’宮崎駿‘
_user = 'sc'
_pwd = 's,514'
global user_status
if user_status == False:
user = input('使用者名:')
pwd = input('密碼:')
if _user == user and _pwd== pwd:
print('Welocome %s login!'%user)
user_status = True
else:
print('Invalid username or password...')
else:
print('Ypu haved already login!')
if user_status:
func(*args,**kwargs) #無論是否傳參都行
return inner
return outer
def home():
print('-------首頁---------')
@login('qq') # xx = login('qq')=outer @outer= outer(jp)=inner
def jp(name):
print('------日本專區------',name)
@login('weixin')
def americ():
print('------美國專區-------')
jp('宮崎駿')
注意: @login('qq') 實際上可拆分為兩部分@ 和 login('qq'),分兩步,第一步,将’qq‘作為login的參數傳入,
傳回outer,此時@outer再将緊接後面的函數名(jp)作為outer的參數傳入,傳回inner給使用者調用的方法即jp('宮崎駿'),
符合條件後跳轉到相關函數功能執行功能。
讀書原為修身,正己才能正人正世;不修身不正己而去正人正世者,無一不是盜名欺世;你把念過的書能用上十之一二,就是很了不得的人了。——朱先生