装饰器
装饰器的定义(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)