目录
一.什么是装饰器
器指的是工具/功能
装饰指的是为被装饰对象添加额外的功能
也就是说:定义装饰器就是定义了一个函数,该函数就是用来为其他函数添加额外的功能的
二.为何要用装饰器
程序的开发需要遵循一个原则:开放封闭原则
开放:指的是对拓展功能开放
封闭:指的是对修改源代码封闭
装饰器就是在不修改被装饰对象源代码以及调用方式的前提为被装饰对象添加上新功能
三.如何用装饰器
1.装饰器初探
有局限性,把index写死了,只能装饰index一个函数对象,没有装饰home
import time
def index(x,y):
time.sleep(0.1)
print('index==>',x,y)
# index(1,2)
def home(name):
time.sleep(0.2)
print("home==>",name)
# home('egon')
def outter():
x = index
def wrapper(a,b):
strat_time=time.time()
x(a,b)
stop_time=time.time()
print('run time is:%s' % (stop_time-strat_time))
return wrapper
index = outter() # f=wrapper
index(1,2) #wrapper()
2.装饰器改进1
改进之后,装饰器可以对函数index,以及函数home添加计算程序运行时间功能
import time
def index(x,y):
time.sleep(0.1)
print('index==>',x,y)
def home(name):
time.sleep(0.2)
print('home====>', name)
def outter(x):
# x=home
def wrapper(*args,**kwargs):
start_time=time.time()
x(*args,**kwargs)
stop_time=time.time()
print('run time is %s'% (stop_time-start_time))
return wrapper
index = outter(index) # index=wrapper
home = outter(home) # home=wrapper
index(1, 2) # wrapper(1,2)
home("egon") # wrapper("egon")
3.装饰器改进2
伪装wrapper,使得被装饰器的返回值也能正同样返回出来
import time
def index(x,y):
time.sleep(0.1)
print('index==>',x,y)
return 123
def home(name):
time.sleep(0.2)
print('home==>',name)
return 456
def outter(x):
def wrapper(*args,**kwargs):
start_time=time.time()
res=x(*args,**kwargs)
stop_time=time.time()
print('run time is %s'%(stop_time-start_time))
return res
return wrapper
index=outter(index) #index=wrapper
home=outter(home) #home=wrapper
res1=index(1,2) #wrapper(1,2)
res2=home('egon') #wrapper('egon')
print('===>',res1)
print('===>',res2)
4.语法糖:增加程序的可读性
这种语法对语言的功能并没有影响,但是更方便程序员使用.
在被装饰的函数体上方顶头写上@装饰器名字
import time
def outter(x):
# x = home
def wrapper(*args, **kargs):
start_time = time.time()
res = x(*args, **kargs) # x("egon")
stop_time = time.time()
print("run time is :%s" % (stop_time - start_time))
return res
return wrapper # 千万不要加括号
@outter # index = outter(index) # index=wrapper
def index(x, y):
time.sleep(0.1)
print('index===>', x, y)
return 456
@outter # home = outter(home) # home=wrapper
def home(name):
time.sleep(0.2)
print('home====>', name)
return 123
res1 = index(1, 2) # wrapper(1,2)
res2 = home("egon") # wrapper("egon")
print("====>", res1)
print("====>", res2)
5.装饰器模板
不同功能的装饰器模板,想要添加什么功能就在被装饰的函数体上方一行顶头写上@该功能的装饰器名字
# 标准模板,没有增加功能
import time
def outter(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
# 计算程序运行时间的装饰器模板
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res = func(*args,**kwargs)
stop_time=time.time()
print(stop_time-start_time)
return res
return wrapper
# 登录功能装饰器模板
def auth(func):
def wrapper(*args,**kwargs):
name=input('请输入用户名: ').strip()
pwd=input('请输入密码: ').strip()
if name == 'juanfu' and pwd =='666':
print('登录成功')
res = func(*args,**kwargs)
return res
else:
print('账号或密码错误')
return wrapper
@auth
def index(x,y):
time.sleep(0.1)
print('index==>',x,y)
return 123
@auth
def home(name):
time.sleep(0.2)
print('home==>',name)
return 456
index(1,2)
home('egon')
6.wraps
将wrapper/装饰器完美伪装成被装饰对象,偷梁换柱
想要保留原函数的文档和函数名属性,需要修正装饰器,functools模块下提供一个装饰器wraps专门用来帮我们实现这件事
from functools import wraps
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
start=time.time
res=func(*args,**kwargs)
stop=time.time
print(stop-start)
return res
# wrapper.__name__ = func.__name__
# wrapper.__doc__ = func.__doc__
return wrapper
@timmer # index=timmer(index) #index=wrapper
def index(x,y):
'''
这是index函数的文档注释
'''
time.sleep(0.2)
print('index==>',x,y)
return 123
# index(1,2)
# print(index.__name__)
help(index)
最完整的模板
from functools import wraps
def outter(func):
@wraps(func)
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper