前言
装饰器的简单功能在前面已经有过介绍(装饰器基础),本篇详细介绍一下装饰器的作用
被装饰函数不带参数
代码部分:
# 在每个函数执行前打印出执行的函数名称
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装饰器这里可能就涉及到底层的知识了,解释不来,我们只需要知道是按这样一个顺序执行的即可