什么是装饰器
装饰器就是给已有函数增加额外功能的函数,它本质上是一个闭包,所以他必须具有闭包的特点。
装饰器的功能特点
1.不修改已有函数的源代码
2.不修改已有函数的调用方式
3.给已有函数增加额外的功能
代码示例
假如我有一个函数来实现评论的功能,如下
def comment():
print("请发表评论”)
输出
请发表评论
但是在发表评论之前是否应该先检查用户是否登录,所以应该在comment中添加检查用户是否登录的功能,但是我们又不想修改comment中的代码,这里我们就可以使用装饰器
def decorate(func):
def in_func():
print("用户已登录")
func()
return in_func
def comment():
print("请发表评论")
# 这里=左边的comment就是in_func,=右边的comment就是func()
comment = decorate(comment)
# 调用方式不变
comment()
输出
用户已登录
请发表评论
解释
1.经过上述代码可以实现在不修改原函数comment()的代码的情况下对comment()函数的功能进行扩展
2.判断decorate()这个函数是不是装饰器的方法:看它里面的参数,里面的参数有且仅有一个参数,且这个参数是函数类型,那么decorate()这个函数就是一个装饰器。
3.为了满足“不修改已有函数的调用方式”这个功能特点,可以创建一个与原函数comment()相同的闭包实例comment,然后comment(),就可以满足条件了。
装饰器的另一种写法
语法糖:
在要装饰的函数的前面添加。
格式:@装饰器名称
def decorate(func):
def in_func():
print("用户已登录")
func()
return in_func
@ decorate # 这行代码相当于 comment = decorate(comment) ,=左边的comment相当于in_func, =右边的comment就是func()
def comment():
print("请发表评论")
comment()
装饰器执行的时机
当前模块加载完成之后,装饰器就会立即执行,对已有函数进行装饰
以上面的代码为例,上面的代码可以是一个模块,这个模块可以起名为my_decorate
当加载my_decorate这个模块的时候,模块中的装饰器decorate()就已经执行了,之后再my_decorate.comment(),就可以实现comment中的功能以及使用装饰器对其扩展的功能。
注意
1.你装饰器中的内部函数一定要与要装饰的函数保持一致。这里的一致指的是:
1)要装饰的函数有没有参数、有几个参数,装饰器中的内部函数也要一样
2)要装饰的函数有返回值,装饰器中的内部函数也要有返回值
2.这里注意装饰器和闭包的区别
装饰器中的参数只能是一个并且参数的类型是函数类型