緣起,在人群中,我看見你---------------裝飾器
阿新 • • 發佈:2021-07-01
裝飾器
裝飾器的定義(what why how)
1.什麼是裝飾器
裝飾器就是裝飾某一個東西的工具
2.為什麼要用裝飾器
因為在源函式程式碼不改變呼叫方法&原始碼給原函式新增新功能,裝飾器是最好的解決工具
3.怎麼用裝飾器
詳見下面
裝飾器的實現思路
""" 現有一個原函式index,想要為其新增一個時間差的功能,我們應該怎麼做呢 """ # 方案一 這就已經修改了他的原始碼了 import time def index(x): start_time = time.time() print(f'welcome to index {x}') time.sleep(3) print(time.time() - start_time) index(1) # 方案二 沒有修改原函式的程式碼&呼叫,但是程式碼冗餘 def index(x): print(f'welcome to index {x}') time.sleep(3) start_time = time.time() index(1) print(time.time() - start_time) start_time = time.time() index(1) print(time.time() - start_time) # 方案三 解決了程式碼冗餘問題,但是原函式的呼叫我們修改了,而且wrapper寫死了,只能呼叫index def index(x): print(f'welcome to index {x}') time.sleep(3) def wrapper(): start_time = time.time() index(1) print(time.time() - start_time) wrapper() # 方案四 我們先搞定呼叫index函式寫死問題 def index(x): print(f'welcome to index {x}') time.sleep(3) def outter(func): def wrapper(): start_time = time.time() func(1) print(time.time() - start_time) return wrapper index = outter(index) index() # 方案五 然後在搞定index函式引數問題 def index(x): print(f'welcome to index {x}') time.sleep(3) def outter(func): def wrapper(*args, **kwargs): start_time = time.time() func(*args, **kwargs) print(time.time() - start_time) return wrapper index = outter(index) index(11) # 方案六 在搞定index返回值的問題,這樣就把wrapper偽裝成index偽裝的很好了 def index(x): print(f'welcome to index {x}') time.sleep(3) return 123 def outter(func): def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(time.time() - start_time) return res return wrapper index = outter(index) res = index(11) print(res) # 方案七 在讓wrapper更像index一點 def index(x): """ 這是index的配置資訊 """ print(f'welcome to index {x}') time.sleep(3) return 123 def outter(func): def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(time.time() - start_time) return res wrapper.__name__ = index.__name__ wrapper.__doc__ = index.__doc__ return wrapper index = outter(index) res = index(11) print(res) # 語法糖 def outter(func): from functools import wraps @wraps(func) def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(time.time() - start_time) return res return wrapper @outter def index(x): """ 這是index的配置資訊 """ print(f'welcome to index {x}') time.sleep(3) return 123 res = index(11) print(res)
裝飾器的總結模板
# 無參裝飾器 def outter(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper # 有參裝飾器 def outter(x): def foo(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper return foo
多個裝飾器
import time def deco1(func): print('----deco1') def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(time.time() - start_time) return res return wrapper() def deco2(func): print('----deco2') def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(time.time() - start_time) return res return wrapper() @deco1 @deco2 def index(x): print(f'{x}') ''' 當多個裝飾器疊加的時候 例如這樣是先從上而下去執行,但是返回值則是從下而上的去返回 所以deco2的返回值是在deco1,deco1的返回值是在真正的index上 '''
有參裝飾器
def login():
name = input('name is :').strip()
pwd = input('pwd is :').strip()
if name == 'ycc' and pwd == '123':
print('login successful')
else:
print('name or pwd error')
def auth(db_type):
def deco(func):
def wrapper(*args,**kwargs):
if db_type == 'file':
login()
print('基於檔案驗證')
# res = func(*args,**kwargs)
# return res
elif db_type == 'mysql':
login()
print('基於資料庫驗證')
# res = func(*args, **kwargs)
# return res
elif db_type == 'ldap':
login()
print('基於ldap驗證')
# res = func(*args, **kwargs)
# return res
res = func(*args, **kwargs)
return res
return wrapper
return deco
@auth(db_type='file')
def index(x, y):
print(x, y)
@auth(db_type='mysql')
def home(name):
# print('welcome %s to home page'%name)
print(f'welcome {name} to home page')
return name
@auth(db_type='ldap')
def transfer():
print('transfer')
index(1, 2)
name = home('ycc')
print(name)