一、定义与应用场景

  • 装饰器​​: 实在不修改被装饰对象的源代码以及调用方式的前提下为被装饰对象添加新功能的可调用对象。
    说人话: 在不修改原函数的代码的情况下,添加新的功能
    ​​添加的位置:
  • 装饰器的功能

引入日志

函数执行时间统计

执行函数前预备处理

执行函数后清理功能

权限校验

缓存

二、简单示例与调用过程

  1. 装饰器只能在调用原函数之前 或者之后 添加功能,而不能在函数的中间添加功能
  2. 只要用装饰器装饰了的函数,那么不管被调用多少次,都是装饰之后的效果
  3. 紧挨着的装饰器先执行,执行完成,交给外部的装饰器装饰
import time
def decorator(func):
def wrapper(*args, **kvargs):
start_time = time.time() # ----->函数运行前时间
func(*args, **kvargs)
end_time = time.time() # ----->函数运行后时间
cost_time = end_time - start_time # ---->运行函数消耗时间
print("%s消耗时间为%s" % (func.__name__, cost_time))
return cost_time
return wrapper # ---->装饰器其实是对闭包的一个应用

def set_pro(func):
def wrapper(*args, **kwargs):
print("这是新添加的 权限验证功能")
ret = func(*args, **kwargs)
return ret
return call_func

def set_log(func):
def wrapper(*args, **kwargs):
print("这是新添加的 log日志的功能")
ret = func(*args, **kwargs)
return ret
return call_func

@set_pro 添加权限的装饰器
@set_log 添加log日志的装饰器
@decorator 装饰器名称就是上面函数名称
def test():
return 'Hello world!'

if __name__ == '__main__':
t = test()
print(t)

简单解释一下

  1. 装饰器​​set_decorate​​ 本身是一个函数,要装饰什么函数?
  2. 一看, 原来要装饰​​test​​​函数, 于是将​​test​​​函数当做参数传入到​​set_decorate​​函数中
  3. ​set_decorate​​​内部又定义了一个函数​​wrapper​​​,等一下, ​​wrapper​​​这个函数有毛用?​​wrapper​​接受的参数又是是的参数?
  4. 哦偶!原来​​wrapper​​​函数才是真正对​​test​​​函数起装饰作用的。​​wrapper​​​接受参数是​​test​​的参数不变
  5. ​set_decorate​​​怎么与两个返回值?
    内部函数​​​wrapper​​​返回的​​test​​​返回值,将其返回到外部函数中 ​​set_decorate​​​ 外部 ​​set_decorate​​函数返回值,就返回啦

三、参数化装饰器

就是在上述的装饰情况下,再次添加一层函数,可用来传递参数

def tags(tag):
def set_decorate(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
res = res + tag
return res
return wrapper
return set_decorate


@tags('1024') 可传参数
def test():
return 'Hello world!'

if __name__ == '__main__':
t = test()
print(t)

四、类装饰器

  1. 初始化方法时保存传递函数的本身,
  2. 在call 方法中执行 保存的函数。执行之前、或之后可进行额外的操作
  • 例一
class check:

def __init__(self, func):
self.f = func

def __call__(self, *args, **kwargs):
print("登陆验证")
self.f()

@check
def userinfo():
print("用户信息")
userinfo()
  • 例二
class check:

def __init__(self, func):
self.f = func

def __call__(self, *args, **kwargs):
print("登陆验证")
self.f()

def userinfo():
print("用户信息")
user = check(userinfo)
user()