美文网首页码农的世界python热爱者
Python装饰器的前世今生!

Python装饰器的前世今生!

作者: Python树苗 | 来源:发表于2018-05-28 20:17 被阅读1次

    这样做逻辑上是没问题的,功能是实现了,但是我们调用的时候不再是调用真正的业务逻辑today函数,而是换成了logging_tool函数,这就破坏了原有的代码结构,为了支持日志功能,原有代码需要大幅修改,那么有没有更好的方式的呢?当然有,答案就是装饰器。

    二、开天辟地

    一个简单的装饰器

    以上也是装饰器的原理!!!

    三、Pythonic世界的初探

    @语法糖 接触 Python 有一段时间的话,对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖,它放在函数开始定义的地方,这样就可以省略最后一步再次赋值的操作

    有了 @ ,我们就可以省去today = logging_tool(today)这一句了,直接调用 today() 即可得到想要的结果。 不需要对today() 函数做任何修改,只需在定义的地方加上装饰器 ,调用的时候还是和以前一样。 如果我们有其他的类似函数,可以继续调用装饰器来修饰函数 ,而不用重复修改函数或者增加新的封装。这样,提高程序可重复利用性,并增加程序的可读性。

    装饰器在 Python 使用之所以如此方便,归因于 Python函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

    2、让装饰器同时支持带参数或不带参数

    如上所示,参数有两种类型,一种是字符串,另一种是可调用的函数类型。因此,通过对参数类型的判断即可实现支持带参数和不带参数的两种情况。

    3、类装饰器

    装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

    (1)示例一、被装饰函数不带参数

    (3)示例三、不依赖初始化函数,单独使用__call__函数实现(体现类装饰器灵活性大、高内聚、封装性高的特点) 实现当一些重要函数执行时,打印日志到一个文件中,同时发送一个通知给用户

    进一步扩展,给LogTool创建子类,来添加email的功能:

    4、装饰函数 -> 装饰类

    (1)函数层面的装饰器很常见,以一个函数作为输入,返回一个新的函数; (2)类层面的装饰其实也类似,已一个类作为输入,返回一个新的类;

    例如:给一个已有的类添加长度属性和getter、setter方法

    五、上古神器

    1、@property -> getter/setter方法

    示例:给一个Student添加score属性的getter、setter方法

    2、@classmethod、@staticmethod

    (1)@classmethod 类方法:定义备选构造器,第一个参数是类本身(参数名不限制,一般用cls) (2)@staticmethod 静态方法:跟类关系紧密的函数

    简单原理示例:

    3、@functools.wraps

    装饰器极大地复用了代码,但它有一个缺点:因为返回的是嵌套的函数对象wrapper,不是原函数,导致原函数的元信息丢失,比如函数的docstring、 name 、参数列表等信息。不过呢,办法总比困难多,我们可以通过@functools.wraps将原函数的元信息拷贝到装饰器里面的func函数中,使得装饰器里面的func和原函数有一样的元信息。

    @functools.wraps让我们可以通过属性__wrapped__直接访问被装饰的函数,同时让被装饰函数正确暴露底层的参数签名信息

    countdown.__wrapped__(1000) # 访问被装饰的函数print(inspect.signature(countdown)) # 输出被装饰函数的签名信息

    4、Easter egg

    (1) 定义一个接受参数的包装器

    @decorator(x, y, z)def func(a, b):pass

    等价于

    func = decorator(x, y, z)(func)

    即:decorator(x, y, z)的返回结果必须是一个可调用的对象,它接受一个函数作为参数并包装它。

    (2)一个函数可以同时定义多个装饰器,比如:

    欢迎关注我的博客或者公众号:https://home.cnblogs.com/u/Python1234/ Python学习交流

    欢迎加入我的千人交流答疑群:125240963

    相关文章

      网友评论

        本文标题:Python装饰器的前世今生!

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