# 裝飾器的做用 —— 不想修改函數的調用方式 可是還想在原來的函數先後添加功能
# 原則: 開放封閉原則
# 開放 : 對擴展是開放的
# 封閉 : 對修改是封閉的
# 語法糖 :@
import time def timmer(f): # 裝飾器函數 def inner(): start = time.time() ret = f() # 被裝飾的函數 end = time.time() print(end - start) return ret return inner @timmer # 語法糖 @裝飾器函數名 def func(): # 被裝飾的函數 time.sleep(0.01) print('老闆好同事好你們好') return '新年好' ret = func() # inner() print(ret) ''' 老闆好同事好你們好 0.010040044784545898 新年好 '''
# 修飾帶參數函數的裝飾器app
def wrapper(func): #qqxing def inner(*args, **kwargs): ret = func(*args, **kwargs) # 被裝飾的函數 return ret return inner @wrapper # qqxing = wrapper(qqxing) def qqxing(a, b): print('{} {}'.format(a, b)) ret = qqxing(1, {'2': 'hello'}) # inner ''' 1 {'2': 'hello'} '''
# functools wraps用法函數
from functools import wraps def wrapper(func): # func = holiday @wraps(func) # 若是不加上wraps語法糖,對於整一個代碼來講,holiday函數並不存在了,有的只是被inner函數裝飾以後的holiday def inner(*args, **kwargs): print('在被裝飾的函數執行以前作的事') ret = func(*args,**kwargs) print('在被裝飾的函數執行以後作的事') return ret return inner @wrapper # holiday = wrapper(holiday) def holiday(day): '''這是一個放假通知''' print('全體放假%s天' % day) return '好開心' print('holiday()的名字:', holiday.__name__) print('holiday()的註釋:', holiday.__doc__) ret = holiday(3) # inner print(ret) '''不加@wraps(func) holiday()的名字: inner holiday()的註釋: None 在被裝飾的函數執行以前作的事 全體放假3天 在被裝飾的函數執行以後作的事 好開心 ''' '''加上@wraps(func) holiday()的名字: holiday holiday()的註釋: 這是一個放假通知 在被裝飾的函數執行以前作的事 全體放假3天 在被裝飾的函數執行以後作的事 好開心 '''
# 裝飾器傳參數spa
# 若是有500個函數用過一次裝飾器了,而後我不想它們走裝飾器了,這時候就須要把語法糖給去掉。一個個刪除語法糖也要刪除500次,過於麻煩,因此就選擇在原裝飾器外部再加一層用於接收FLAG參數 import time FLAG = False def timmer_out(flag): def timmer(func): def inner(*args,**kwargs): if flag: start = time.time() ret = func(*args,**kwargs) end = time.time() print(end-start) return ret else: ret = func(*args, **kwargs) return ret return inner return timmer # timmer = timmer_out(FLAGE) @timmer_out(FLAG) #wahaha = timmer(wahaha) def wahaha(): time.sleep(0.1) print('wahahahahahaha') @timmer_out(FLAG) def erguotou(): time.sleep(0.1) print('erguotoutoutou') wahaha() erguotou() '''FLAGE = True時 wahahahahahaha 0.10003066062927246 erguotoutoutou 0.10085654258728027 ''' '''FLAGE = False時 wahahahahahaha erguotoutoutou '''
# 多個裝飾器裝飾一個函數code
def wrapper1(func): def inner1(): print('wrapper1 ,before func') ret = func() print('wrapper1 ,after func') return ret return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') ret = func() print('wrapper2 ,after func') return ret return inner2 def wrapper3(func): def inner3(): print('wrapper3 ,before func') ret = func() print('wrapper3 ,after func') return ret return inner3 @wrapper3 @wrapper2 @wrapper1 def f(): print('in f') return '哈哈哈' print(f()) ''' wrapper3 ,before func wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper2 ,after func wrapper3 ,after func 哈哈哈 '''
裝飾器題目orm
# 一、編寫裝飾器,爲多個函數加上認證的功能(用戶的帳號密碼來源於文件),要求登陸成功一次,後續的函數都無需再輸入用戶名和密碼blog
FLAG = False def login(f): def inner(): global FLAG if FLAG: ret = f() else: username = input('Please input your username:') password = input('Please input your password:') with open('login.txt', 'r') as fr: a, b = fr.read().split(' ') if username == a and password == b: FLAG = True ret = f() return ret else: print('username or password error!') return return inner @login def shoplist_add(): print('add...') @login def shoplist_del(): print('del...') shoplist_add() shoplist_del() ''' Please input your username:admin Please input your password:123 add... del... '''
# 二、編寫裝飾器,爲多個函數加上記錄調用功能,要求每次調用函數都將被調用的函數名稱寫入文件input
import datetime def outer(f): def inner(): with open('log.txt', 'a+') as fw: time = datetime.datetime.now() fw.write('{0}\t{1}\n'.format(time, f.__name__)) fw.close() ret = f() return ret return inner @outer def func1(): print('func1') @outer def func2(): print('func2') func1() func2()