看了不少python关于装饰器文章,觉得还挺实用,发贴来mark一下(以前做笔记总会长时间不看就忘记,放这里应该不会忘了吧 - -)
先来看一个简单的知识点:
def a(): print("I'm a") #a 代表这个函数,在Python中函数名只是个指向函数首地址的函数指针而已 a() #执行函数
ok,接下来开始讲装饰器,看下面的小例子:
def a(func): print("a running!") return func @a def b(): print("b running!") b()
当python读到@a的时候,其实执行的相当于 b=a(b),将下面的函数作为参数带入执行。这样我们在带入读下是不是变得很简单了,就是将b作为参数带入函数a中执行,再把函数a返回的结果赋值给b,等于重新定义了函数b;再来看内部的执行过程:
直接从@a开始,@a <==> b=a(b)
1.执行参数为b的a函数,打印“a running”
2.返回b,并将b赋值给b(这样也等于啥也没变!)所以也没有什么卵用!接下来我们再看一个开发中常用到的示例
示例2:
def a(b): print("a running!") def c(): print("c running!") return b() return c @a def b(): print("b running!") b()
再看看这个函数的执行过程:
1.先将@a <==> b=a(b) ,相当于函数b等于被重新定义为a(b)的返回结果,
2.跳转a(b)的执行过程,先打印a running! 说明a运行了,接下来定义一个函数c,没啥输出,因为还没调用这个函数!注意这里的c函数return的b()的不是一个函数了啊,而是这个函数执行的结果,是将这个函数的结果作为返回值!这么做是有原因的(请看最后)
3.接下来才是return一个函数c,是不是相当于b=c(这就很有用了,在不改变函数b的情况下拓展了b的功能,真爽啊!)
所以最后这个b被定义成了这样:
b=def c(): print("c runing!") return b()
4.再来执行b(),看看是不是输出了 c running !,又运行b()作为返回结果给调用者,当然函数b没有定义返回内容额,所以只运行了b()
最后解释下为什么要用return b(),return b()是运行b(),然后将返回的结果再返回,
这样想想看,没有使用装饰器之前,我调用b()是不是就是返回b()的结果啊,
现在加上装饰器,返回的是不是依然是b()的结果,这样对外看来我们调用b好像完全没有改变,但是实际上b在运行之前已经运行了我们的拓展功能了。。。不得不说666啊
总的来看其实主要就是@a 等价于 b=a(b) 理解了这个就ok啦,好处就是在不影响b函数的情况下,因为执行b还是返回原来的b返回的内容,增加了b函数的功能,是不是挺方便!!