一、装饰器的定义:
就是在不修改原有函数代码的前提下,给已有函数增加额外功能的函数,它本质上就是一个闭包函数
Python中有自带的装饰器:@staticmethod
二、装饰器的功能特点:
- 不修改已有函数的源代码
- 不修改已有函数的调用方式
- 给已有函数增加额外的功能
三、实例
1、无参函数
假设我们有一个登陆函数,若我们想修改该函数,即增加一个验证登录的功能。此时我们可以直接修改原函数的代码,但是在实际生产开发中不合理,相比之下我们更会选择使用装饰器:
本质就是一个闭包函数原理:
1、在函数嵌套(函数里面再定义函数)的前提下
2、内部函数使用了外部函数的变量(还包括外部函数的参数)
3、外部函数返回了内部函数
代码中传入的func参数是上面的登录函数,然后我们在登录函数前增加一个验证登录的功能。
注意: 闭包函数写完之后,只需要在原登录函数的开头加一个:@func_out便可增加新的功能。当我们运行程序时,添加装饰器那行代码会先执行,当使用装饰器时(“@func_out”)相当于计算机默认执行了:login=func_out(login)。
最后重新调用login()函数便可使用增加了新功能的函数了。
结论:
1、调用login()相当于==>func_in(), 调用被装饰的函数就相当于调用闭包中的内层函数
2、外层函数的参数 func ==> 原始的login
2、有参函数
运行结果:
结论:
1、调用my_test()相当于==>func_in(), 调用被装饰的函数就相当于调用闭包中的内层函数
2、外层函数的参数 func ==> 原始的my_test
3、带返回值的函数
结果分析: func()有没有返回值跟func_in 没有关系,默认返回None。
所以当调用my_test()时候相当于调用func_in(),而func_in()是没有返回值的,默认返回None.
解决办法:就是将func_in()函数中的func()用一个变量来接收,然后将这个变量通过return来返回.
4、通用版本装饰器
def func_out(func):
#函数中如果没有return 证明函数是没有返回值的
def func_in(*args,**kwargs):
ret = func(*args,**kwargs)
return ret
return func_in
@func_out
def my_test(*args,**kwargs):
return 100
a = my_test()
print(a)
5、多个装饰器
def func_out01(func01):
print("this is func_out01")
def func_in01():
print("this is func_in01")
func01()
return func_in01
def func_out02(func02):
print("this is func_out02")
def func_in02():
print("this is func_in02")
func02()
return func_in02
#就近原则,谁距离被装饰函数近,谁先被执行
@func_out01
@func_out02
def my_test():
print("my_test")
my_test()
运行结果:
结果分析:
当运行程序后是从上往下执行的,先执行 @func_out01,但是因为装饰器只能装饰函数,装饰器是装饰不了函数的。
于是执行下一行代码:@func_out02,执行my_test = func_out02(my_test),即my_test作为函数传入了 func_out02,先显示了“this is func_out02”,然后将func_in02返回了。
即生成了新函数:
@func_out02
def my_test():
print("my_test")
此时,@func_out01便可执行,同理先显示了“this is func_out01”,然后将func_in01返回了。
6、带参数的装饰器
(1)定义:
带参数的装饰器只需要在原有不带参的装饰器外再套上一个函数,该最外层函数中可定义参数,嵌套里面的函数可引用该参数。
def my_func(num):# fum = 10
def func_out(func):
def func_in(a,b):
if num == '*':
print("相乘为:",a*b)
if num == '+':
print("相加为:",a+b)
func(a,b)
return func_in
return func_out
@my_func('*')
# 1 my_func
# 2 @func_out
# 3 my_test = func_out(my_test)
def my_test(a,b):
print(a,b)
#1 my_test()==> func_in()
#2 func() ==>原始的my_test()
my_test(3,4)
运行结果: