美文网首页
Python装饰器(4)带参数的装饰器

Python装饰器(4)带参数的装饰器

作者: Bblsc | 来源:发表于2018-10-05 17:21 被阅读0次

内容纯属个人理解,不对之处,欢迎指正。

之前说过,装饰器其实就是函数,既然是函数,那就可以有参数,装饰器也不例外,接下来我们来分析带参数的装饰器。

如何构造带参数

带参数倒是很简单,在装饰的时候给装饰函数写上参数就行,但是具体的装饰器函数该怎么写,我们需要思考一下。
我们想让它带参数,无非就是对被装饰函数的执行进行一定条件的限定设置,也就是说在函数执行之前,函数就必须具备这个条件,那么这样的话,就有两种选择,要么在传递func以后传递参数;要么在传递func之前传递参数。
在想法上,两种其实是都可以的,但是,我们传递参数的时候是给装饰器传递,也就是说,装饰器函数首先接收的是装饰器函数的参数,然后带着这个参数再去装饰函数。因此,我们就必须先处理装饰器函数的参数,然后再去处理被装饰的函数。
所以在实现上,我们应该这样去构造带参装饰器函数:

def deco_para(parameter):
    def deco_func(func):
        def wrapper(*args, **kwargs):
            print(parameter)
            func(*args, **kwargs)
        return wrapper
    return deco_func

带参装饰器示例

def deco_para(parameter):
    print('enter deco_para')

    def deco_func(func):
        print('enter deco_func')

        def wrapper(*args, **kwargs):
            print('enter wrapper')
            print(parameter)
            print('---wrapper: before func---')
            func(*args, **kwargs)
            print('---wrapper: after func---')

        return wrapper

    return deco_func


@deco_para(123)
def foo():
    print('---foo---')


if __name__ == '__main__':
    print('--start--')
    foo()

运行结果:

enter deco_para
enter deco_func
--start--
enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---

结果应该不用多说,先接收参数123,然后接收函数foo,最后执行wrapper。

装饰过程解析--多次输出问题

我们解析下过程

deco_func = deco_para(123)  # 接收参数123
wrapper = deco_func(foo)  # 接收函数foo
foo = wrapper  # 重命名
foo()  # 执行foo

如果你试着按这个过程去执行代码,会发现一个问题,wrapper函数里面的代码执行了2次。

enter deco_para
enter deco_func
enter deco_para
enter deco_func
enter wrapper
123
---wrapper: before func---
enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---
---wrapper: after func---

我们看下究竟是怎么回事。

# 程序执行,扫面到装饰器,执行装饰器函数内部代码
1.enter deco_para
2.enter deco_func

# deco_para(123)接收参数123时执行3
3.enter deco_para

# deco_func(foo)接收函数foo时执行4
4.enter deco_func

# foo()执行foo()
5.enter wrapper
6.123
7.---wrapper: before func---

8.enter wrapper
9.123
10.---wrapper: before func---
11.---foo---
12.---wrapper: after func---

13.---wrapper: after func---

在之前解析装饰器的时候就提到过,函数被装饰以后,就不是原来的函数了,也就是说上面所执行的foo,其实是wrapper。
那么wrapper里面有什么东西呢?

print('enter wrapper')
print(parameter)
print('---wrapper: before func---')
func(*args, **kwargs)
print('---wrapper: after func---')

似乎执行结果应该是

enter wrapper
123
---wrapper: before func---
---foo---
---wrapper: after func---

但是事实上,此时的wrapper里面的func已经不是原来的func。
回顾闭包:引用了自由变量的函数即是一个闭包,这个被引用的自由变量和这个函数一同存在, 即使已经离开了了创造它的环境也不例外
那么可以推测,此时的被装饰函数应该具有了额外的东西,这些东西就是

print('enter wrapper')
print(parameter)
print('---wrapper: before func---')
print('---wrapper: after func---')

由此也就可以知道为什么wrapper里面的代码执行了2次:就是在执行到func(*args, **kwargs)的时候,执行了功能丰富以后的func。

相关文章

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • 透析Python装饰器--透过现象看本质

    》眼花缭乱 Python的装饰器(也称语法糖)大致分为这几类: 无参数装饰器 有参数装饰器 装饰类的装饰器 无参数...

  • 透析Python装饰器-------------透过现象看本质

    》眼花缭乱 Python的装饰器(也称语法糖)大致分为这几类: 无参数装饰器 有参数装饰器 装饰类的装饰器 无参数...

  • TypeScript: 类的装饰器(三)

    带参数的类的装饰器 学习 python 的同学应该知道,python 中也有装饰器,而且 python 中的众多框...

  • Python | 装饰器

    使用场景 装饰器 ' @ ' 使用 带参数装饰器 装饰器类

  • Python装饰器(4)带参数的装饰器

    内容纯属个人理解,不对之处,欢迎指正。 之前说过,装饰器其实就是函数,既然是函数,那就可以有参数,装饰器也不例外,...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • Python - 学习理解带参数的装饰器

    理解带参数的装饰器 参考文章 Python精进-装饰器与函数对象 加了装饰器这段代码从一个函数定义(不会执行任何东...

  • python装饰器

    1.装饰器 2.带装饰器的参数

网友评论

      本文标题:Python装饰器(4)带参数的装饰器

      本文链接:https://www.haomeiwen.com/subject/tpjqaftx.html