裝飾器有非常強大的功能,可以不修改函數源代碼和調用方式,就給函數加上了對應想要的功能,簡直就是 修飾函數的利器。 上一篇文章:初學者python筆記(裝飾器、高階函數、閉包)已經非常詳細的剖析了裝飾器的原理,本篇就來實現就來具體實現一個登陸驗證的案例(源碼可以直接使用)
修飾帶參數的函數:
被修飾的函數參數個數是不固定的,而要修改參數個數就肯定需要修改裝飾器和原函數,違反了裝飾器的修改原函數源代碼的原則。
而基本裝飾器本來是不帶有參數的,如果調用原函數需要傳入參數怎麼辦?可以如下操作:
#裝飾器
import time
def timmer(func):
def wrap(*args,**kwargs):
#一個接收列表,一個接收字典,用容器作爲參數就可以不限參數個數了
#相當於:foo('夏洛特玲玲','50','female','拿破崙','卡塔庫慄'),
#args=['夏洛特玲玲','50','female','拿破崙','卡塔庫慄'],kwargs={ }
start_time = time.time() #給裝飾器加的功能
res = func(*args,**kwargs) #在裝飾器中運行函數,並且用一個變量來接收以返回原函數的返回值
stop_time = time.time()
print('函數運行了{}秒'.format(stop_time - start_time))
return res #返回原函數的返回值
return wrap #函數的返回值是函數,所以爲高階函數
#原函數
@timmer #語法糖的使用,使原函數即foo函數被裝飾。相當於foo = timmer(foo)語句
def foo(name,age,sex,weapen,son):
time.sleep(3)
print('test函數運行完畢!\n名字:%s,年齡:%s, 性別:%s,武器:%s,兒子:%s' %(name,age,sex,weapen,son))
return '這是test的返回值' #爲了實現把原函數的返回值也接收到
#調用被修飾後的原函數
foo('夏洛特玲玲','50','female','拿破崙','卡塔庫慄') #運行原函數,方式不變,滿足原則
#可以看到,加了*args和*kargs後就無論多少個參數都能正常運行了
運行結果:
test函數運行完畢!
名字:夏洛特玲玲,年齡:50, 性別:female,武器:拿破崙,兒子:卡塔庫慄
函數運行了3.0121726989746094秒
登陸驗證的實現
user_list = [ #查詢密碼的列表,包含所有的賬號密碼
{'name':'路飛','passwd':'1111'}, #重點知識:因爲你輸入的是字符串,
{'name':'索隆','passwd':'2222'}, #所以你字典的value也必須是字符串格式,不能是數字格式的值
{'name':'羅','passwd':'3333'},
{'name':'基德','passwd':'4444'}
]
current_dic = {'username':None ,'login':False} #記錄當前用戶登陸狀態的字典
#帶驗證功能的裝飾器
def auth_func(func):
def wrapper(*args, **kwargs):
if current_dic['username'] and current_dic['login']:
#如果都爲True就執行,即輸入過賬號密碼後就不需要再次輸入了
res = func(*args, **kwargs) #直接執行,不需要再輸入賬號密碼
return res
#否則就輸入賬號密碼
username = input('用戶名:').strip() #讓用戶輸入登陸信息
passwd = input('密碼:').strip()
#遍歷字典來匹配賬號密碼是否正確
for user_dic in user_list: #user_dic是用來遍歷列表中每個字典的變量
#print(user_dic['name'],user_dic['passwd'])
if user_dic['name'] == username and user_dic['passwd'] == passwd: #驗證賬號密碼
#print(user_dic['name'],user_dic['passwd'])
#輸入正確就記錄下登陸狀態,用記錄狀態的字典
current_dic['username'] = username
current_dic['login'] = True
#print(current_dic['login'])
res = func(*args, **kwargs) #接收原函數返回值
return res
#else跟for成對,表明如果你輸入的連用戶名都不存在,那就不用遍歷了
else:
print('用戶名或密碼錯誤!!!')
return wrapper #如果密碼錯誤就不會有返回值,而是返回wrapper重新再輸入
@auth_func
def index():
print('歡迎來到淘寶主頁!')
@auth_func
def home(name):
print('歡迎%s回家' %name)
@auth_func
def shopping_car(name):
print('%s的購物車裏有:%s、%s、%s' %(name,'連衣裙','海賊手辦','迪迦凹凸曼'))
print('初始用戶狀態:',current_dic)
index()
print('輸入後用戶狀態:',current_dic)
home('您') #該函數無論傳入什麼值都可以,只是給函數內部多一個全局變量
shopping_car('您')
運行結果:
初始用戶狀態: {‘username’: None, ‘login’: False}
用戶名:索隆
密碼:2222
歡迎來到淘寶主頁!
輸入後用戶狀態: {‘username’: ‘索隆’, ‘login’: True}
歡迎您回家
您的購物車裏有:連衣裙、海賊手辦、迪迦凹凸曼
以上就是裝飾器案例的實現,如果你看了上一篇裝飾器原理的文章,本篇案例肯定是可以理解的