2020年10月29日 11:45:39
“”“装饰器的作用:
1、调用原函数
2、为其增加新功能”""
第一步:
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
第二步:
def outter(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
第三步:增加新功能
def timer(func):
def wrapper(*args, **kwargs):
start = timer.time()
res = func(*args, **kwargs)
stop = timer.time()
print(stop - start)
return res
return wrapper
作业:
“认证功能”,在确认用户名和密码后再执行
def auth(func):
def wrapper(*args, **kwargs):
name = input("your name:").strip()
pwd = input("your password:").strip()
if name == "egon" and pwd == "123":
res = func(*args, **kwargs)
return res
else:
print("账户密码错误")
return wrapper
@auth
def index():
print("from index")
index()
运行结果:
your name:ook
your password:123
账户密码错误
或者
your name:egon
your password:123
from index
----------------------分界线--------------------
扩展
1、 outter, timer, wrapper, auth是什么?是一个个名字,名字指向的就是内存地址。
2、名字后面加括号(),就会触发代码的运行。例如:
3、@print 等于 print(home) --> home这个名字指向的是 home函数的内存地址
@print
def home(a, b, c):
pass
运行结果:
<function home at 0x7f95e30ccf28>
经过上面的优化后发现,print(index)的时候,
可以发现结果是 wrapper的内存地址,而不是原函数index的内存地址,
原函数的文档注释也无法显示出来,所以需要再修改一下。
def timer(func):
def wrapper(*args, **kwargs):
start = timer.time()
res = func(*args, **kwargs)
stop = timer.time()
print(stop - start)
return res
wrapper.__name__ = func.__name__
wrapper.__doc__ = func.__doc__
return wrapper
@timer # index = timer(index)
def index(x, y):
"""这个是主页功能"""
print(x, y)
print(index.__name__)
print(index.__doc__) # help(index) 这两个都是查看函数注释的功能
运行结果:
index
这个是主页功能
修改
手动将原函数的属性赋值给wrapper函数,肯定会有遗漏,所以需要调用一个模块,这是python提供的一个装饰器。
目的:将原函数的属性都覆盖给wrapper
from functools import wraps
def outter(func):
@wraps(func)
def wrapper():
XXX
return wrapper
有参装饰器(套了三层的函数)
‘’’
第二层函数outter的参数(func)是为了获取原函数的内存地址,
因为 语法糖 的原因,参数只能唯一, @outter ==> func = outter(func)
第一层函数wrapper的参数(*args, **kwargs) 是为了获取原函数的参数
所以,第一、二层的参数不能改动
所以,当需要其他参数时,就要第三层函数了
‘’’
有参装饰器模板
def 名为ABC的有参装饰器 (x, y, z): # 参数可以有多个
def outter(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
return outter
@ABC(1, y = 2, z = 3)
def 被装饰对象():
pass