关于装饰器,看了几篇文章,总结下

装饰器是为了动态为函数增加功能,而不改变函数的代码,而存在的。编写一个高阶函数,让他接收另一个函数,在内部对其包装,是为装饰器。

装饰器的本质就是一个函数,用来修饰你要装饰的函数,别想复杂了。

调用装饰器,下面是要修饰的函数,则下面的函数就整体看做一个变量,传给了装饰器函数,传过去之后,当时就返回了装饰器函数的内部函数,即此时:传入函数=装饰器内部函数。
在这里插入图片描述
如图:f=foo()=bar, f()=bar()
这里要注意一点,就是装饰器函数在装饰了被装饰函数之后,其外层代码会立刻执行,被装饰函数立马等于内部函数,然后被装饰函数调用时,内部函数才被调用。

再看多层装饰器执行顺序:

在这里插入图片描述
在这里插入图片描述
为什么是先执行 inner_b 再执行 inner_a 呢?为了彻底看清上面的问题,得先分清两个概念:函数和函数调用。上面的例子中 f 称之为函数, f(1) 称之为函数调用,后者是对前者传入参数进行求值的结果。在Python中函数也是一个对象,所以 f 是指代一个函数对象,它的值是函数本身, f(1) 是对函数的调用,它的值是调用的结果,这里的定义下 f(1) 的值2。同样地,拿上面的 decorator_a 函数来说,它返回的是个函数对象 inner_a ,这个函数对象是它内部定义的。在 inner_a 里调用了函数 func ,将 func 的调用结果作为值返回。

装饰器函数在被装饰函数定义好后立即执行
其次得理清的一个问题是,当装饰器装饰一个函数时,究竟发生了什么。现在简化我们的例子,假设是下面这样的:
在这里插入图片描述
所以,当解释器执行这段代码时, decorator_a 已经调用了,它以函数 f 作为参数, 返回它内部生成的一个函数,所以此后 f 指代的是 decorater_a 里面返回的 inner_a 。所以当以后调用 f 时,实际上相当于调用 inner_a ,传给 f 的参数会传给 inner_a , 在调用 inner_a 时会把接收到的参数传给 inner_a 里的 func 即 f ,最后返回的是 f 调用的值,所以在最外面看起来就像直接再调用 f 一样。
当理清上面两方面概念时,就可以清楚地看清最原始的例子中发生了什么。

当解释器执行下面这段代码时,实际上按照从下到上的顺序已经依次调用了 decorator_a 和 decorator_b ,这是会输出对应的 Get in decorator_a 和 Get in decorator_b 。 这时候 f 已经相当于 decorator_b 里的 inner_b 。但因为 f 并没有被调用,所以 inner_b 并没有调用,依次类推 inner_b 内部的 inner_a 也没有调用,所以 Get in inner_a 和 Get in inner_b 也不会被输出。

然后最后一行当我们对 f 传入参数1进行调用时, inner_b 被调用了,它会先打印 Get in inner_b ,然后在 inner_b 内部调用了 inner_a 所以会再打印 Get in inner_a, 然后再 inner_a 内部调用的原来的 f, 并且将结果作为最终的返回。这时候你该知道为什么输出结果会是那样,以及对装饰器执行顺序实际发生了什么有一定了解了吧。

自我总结:多层装饰器时,定义函数时先执行内部decorator再执行外部decorator,最后落到外部decorator的内层函数上(wapper或inner),调用函数时(f()),先运行外部decorator的内层函数,然后逐步向里执行,直到最终执行被装饰函数(内核),结束。
定义函数后:由内到外(被装饰函数定义好了就会立即执行)
调用函数后:由外到内(调用时接着上面定义好的结果继续执行)

欢迎讨论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值