装饰器的简单功能在前面已经有过介绍(装饰器基础),本篇详细介绍一下装饰器的作用
代码部分:
# 在每个函数执行前打印出执行的函数名称 def print_log(func): def wrapper(): print("当前执行的函数名为:",func.__name__) func() return wrapper @print_log def send_word(): print("正在执行send_word函数") @print_log def send_video(): print("正在执行send_video函数") send_word() send_video()执行结果:
代码部分:
# 操作的前提需要登录,必须输入正确的name和pwd才可以继续执行func def login(func): def wrapper(name,pwd): if name == "admin" and pwd == "123456": print("登录成功,可以继续操作!!") func() # 3.func()等同于send_word(),这里会执行send_word函数 else: print("还未成功登录,不能操作") return wrapper @login # 1.这里相当于send_word=login(send_word);会去执行login函数,返回wrapper def send_word(): print("这是发布的内容") # 2.send_word()等同于wrapper()此时会去执行wrapper函数; # wrapper有两个必填函数,所以被装饰函数send_word()需要也需要传递两个参数 # 不传参数运行会报错wrapper() missing 2 required positional arguments: 'name' and 'pwd' send_word("admin","123456")执行结果:
带参数组,是因为不确定每个被装饰函数的参数个数,一般会用参数组来传参
在第一个demo的基础上优化一下
代码部分:
# 在每个函数执行前打印出执行的函数名称 def print_log(func): def wrapper(*args, **kwargs): print("当前执行的函数名为:",func.__name__) func(*args, **kwargs) return wrapper @print_log def send_word(*args, **kwargs): print("正在执行send_word函数,输出结果:{}",(args,kwargs)) @print_log def send_video(*args, **kwargs): print("正在执行send_video函数,输出结果:",(args,kwargs)) send_word("suner","wang") send_video(name="suner",age=20)执行结果:
上面的装饰器默认只能传递一个func参数,假设我们需要装饰器实现不同的装饰效果,可以在外层再封装一下
代码部分:
def print_log(category): def decorator(func): def wrapper(*args, **kwargs): if category == "func_name": print("当前执行的函数名为:", func.__name__) elif category == "func_dir": print("当前执行的函数dir为:", func.__dir__) return func(*args,**kwargs) return wrapper return decorator @print_log("func_name") # 相当于@decorator def send_word(*args, **kwargs): print("正在执行send_word函数,输出结果:",(args,kwargs)) @print_log("func_dir") # 相当于@decorator def send_video(*args, **kwargs): print("正在执行send_video函数,输出结果:",(args,kwargs)) send_word("suner","wang") send_video(name="suner",age=20)
执行结果:
装饰器可以是一个函数,也可以是一个类
使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。
代码部分:
class PrintLog(): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): print("当前执行的函数名为:", self.func.__name__) self.func(*args, **kwargs) @PrintLog def send_word(*args, **kwargs): print("正在执行send_word函数,输出结果:",(args,kwargs)) send_word("suner",20)
执行结果:
代码部分:
def decorator_001(func): print("-----001-----") def wrapper(*args,**kwargs): print("这是001装饰器") func(*args,**kwargs) return wrapper def decorator_002(func): print("-----002-----") def wrapper(*args,**kwargs): print("这是002装饰器") func(*args,**kwargs) return wrapper def decorator_003(func): print("-----003-----") def wrapper(*args,**kwargs): print("这是003装饰器") func(*args,**kwargs) return wrapper @decorator_001 @decorator_002 @decorator_003 def send_word(*args, **kwargs): print("正在执行send_word函数,输出结果:",(args,kwargs)) send_word("suner",20)执行结果:
由打印的003~001可以看出多个装饰器之间的执行顺序是从里往外执行的,至于为什么先打印001装饰器这里可能就涉及到底层的知识了,解释不来,我们只需要知道是按这样一个顺序执行的即可