装饰器
装饰器是Python语言一个别具特色的功能,龙哥在码日志处理程序的时候经常用到,可见它十分常用,值得认真学习并掌握。
为什么Python可以有装饰器
这涉及到python拥有的三个特殊功能
第一,python的函数可以赋给变量
#定义了一个没有参数的函数
def func():
print("hello ABT")
#把函数赋给变量a,这里因为有小括号,所以函数得到了调用,print执行
a = func()
#这里因为没有小括号,所以函数没有得到调用,print不执行
b = func
运行结果:
hello ABT
那么上述b变量赋值的特殊之处在哪里呢?
下面以有参数的函数为例进行试验:
#定义了有一个参数x的函数
def func(x):
print(x*3)
#这里因为没有小括号,所以函数没有得到调用,print不执行
a = func
#这里函数才开始执行
#AMAZING!!
#变量a变成了一个函数!!
a(4)
运行结果:
12
在a(4)处打上断点,进一步探究原因:
原来a的地址其实就是func的地址
不由自主会联想到pyhton的另一个特性——浅拷贝
第二,python函数可以作为另一个函数的参数
既然python的函数可以被赋给一个变量,那么顺理成章,它也可以成为另一个函数的参数
def func1():
print("func1 called")
def func2(a):
a()
print("func2 called")
func2(func1)
运行结果:
func1 called
func2 called
第三,python的函数内可以嵌套地定义函数
通过上述三种语法的应用,可以得到这段代码:
def func_outer(func_test):
def func_inner():
print("func_test not called yet")
func_test()
print("func_test called")
return func_inner
def func_another():
print("func_another called")
a = func_outer(func_another)
a()
运行结果:
func_test not called yet
func_another called
func_test called
使用装饰器的代码:
def func_outer(func_test):
def func_inner():
print("func_test not called yet")
func_test()
print("func_test called")
return func_inner
@func_outer
def func_another():
print("func_another called")
func_another()
运行结果同上
可以看出,装饰器的效果等价于:
func_another = func_outer(func_another)
两个装饰器对一个函数体的作用顺序:
def func_outer(func_test):
def func_inner():
print("func_test not called yet")
func_test()
print("func_test called")
return func_inner
@func_outer
@func_outer
def func_another():
print("func_another called")
func_another()
运行结果:
func_test not called yet
func_test not called yet
func_another called
func_test called
func_test called
可以看到,先执行第二个装饰器,再执行第一个装饰器