闲话python 35: 谈一谈装饰器

发表时间:2020-02-26

在python程序中常常看到某些函数前有一个@符号语句修饰,这就是装饰器,也称修饰器。无论是在一些第三方的库中还是python内置的模块,装饰器都有大量使用的案例。使用装饰器可以改变所定义函数的一些行为,或者在所定义函数运行之前进行一些参数检查的工作,这个语法在实际使用中为开发者带来极大的便利。特别是对于某一些函数可以使用同样的装饰器进行修饰的时候,代码重用程度得到很不错地提升。

1. 常用的装饰器

python内建的装饰器也有不少,这里就讨论一下最常用的几个。在定义一个类时,有时需要封装一些函数,这些函数不依赖具体的实例对象,而是属于类本身。这时就需要用到staticmethod或者classmethod这两个修饰器。这样可以比较紧凑且合乎逻辑地组织代码。此外还有一个常用的修饰器是property,这个修饰器的作用是将一个函数名包装成对象可读属性。与之配套的还可以这是这个可读属性的可写属性。以下演示就足以说明这几个常用属性的使用方法。

闲话python 35: 谈一谈装饰器

常用的装饰器

从以上的几个修饰器使用例子可以看出,修饰器的作用主要是在函数运行之前进行一些预处理工作,特别是参数检查和验证,函数执行环境准备以及函数调用方式调整。proprtty从修饰器可以提供只读属性,这对于类的封装而言可以控制得更加精细一点。

2. 装饰器原理和深坑

装饰器用起来显得非常神奇和神秘,那么装饰器的原理是怎么样的呢?说到底,装饰器就是使用一个函数包装另一个函数。 说得更加通用一点,装饰器就是使用一个可调用对象包装另一个可调用对象 。函数是一种可调用对象,定义了 call 方法的类所创建的对象也是一个可调用对象,所以函数和带有 call 方法的对象都可以作为修饰器或者被修饰器修饰。那么有个问题,函数参数该如何传递呢? 在python中,函数参数有两大类,一类是位置参数,一类是键值对参数。 这两个参数正好可以使用元组传参和词典传参解决,关于python中参数传递的问题可以阅读我的另一篇文章 https://www.toutiao.com/i6737184785585668619/ 。说起来可能比较绕,以下使用函数这种可调用对象演示一下修饰器的原理。

闲话python 35: 谈一谈装饰器

装饰器原理和深坑

从以上演示中可以看出,我们在调用所定义的函数之前,修饰器的函数先被调用,然后修饰器的函数在调用我们所定义的函数。普通使用这样的修饰器也没什么大问题,但是我们查看以下所定义函数的一些属性,发现不对劲,因为函数属性被修改成修饰器中函数的属性了,这一点并不是我们所期望的。要就解决这个问题,就需要使用python中的一个模块来对修饰器中函数接口进行一次装饰。

闲话python 35: 谈一谈装饰器

改善的装饰器

使用@wraps()装饰一些修饰器内部的函数之后,外部所定义函数的属性就符合预期了。我们在修饰器的一些测试点打印了信息,标记结果显示,函数中语句的执行顺序可能和大家预想得不一致,但却是符合程序运行逻辑的。 因此,不建议在修饰器的函数外部进行任何操作,因为这些操作的具体执行情况可能与开发者预想的不一致。 也就是说,如果开发者不明确知道修饰器中程序执行的逻辑,尽量将所有的逻辑都写入到修饰器内部的函数中,从而保证正常执行。

3. 带参数的装饰器

在使用第三方库的时候,有时会向装饰器传入参数,比如django中的admin.register()注册修饰器。其实这种带参数的修饰器只是将原有的修饰器多加了一层函数封装而已。以下的演示可以说明带参数的装饰器的定义方法。

闲话python 35: 谈一谈装饰器

带参数的装饰器

到此,关于python中的装饰器讨论完毕。这里是指谈论了装饰器的基本原理和几个最常用的装饰器,在实际使用中,装饰器可以做的事情非常多,如果打算更深入了解python的话,装饰器是必须要掌握的,因为开发工程量稍微大一点就需要考虑利用装饰器的特性提升开发效率。本文的notebook版文件在github上cnbluegeek/notebook仓库共享,欢迎感兴趣的朋友前往下载。

微配音

文章来源互联网,尊重作者原创,如有侵权,请联系管理员删除。邮箱:417803890@qq.com / QQ:417803890


Python Free

邮箱:417803890@qq.com
QQ:417803890

皖ICP备19001818号
© 2019 copyright www.pythonf.cn - All rights reserved

微信扫一扫关注公众号:

联系方式

Python Free