如何消除Python装饰器产生的副作用

装饰器给我们带来高效的编程,但也会产生一些问题,而这些问题又容易被我们大家忽视 。
装饰器产生的副作用在Python世界里,一切皆对象,所以函数也是对象,函数有一些内置属性,例如:__name__、 __module__ 、__doc__ 和__dict__等 。
如果使用装饰器修饰函数,那么函数的内置属性值会发生变化,这将不利于调试,定位bug位置,这就是装饰器产生的副作用!
结合示例了解装饰器的副作用:

如何消除Python装饰器产生的副作用

文章插图
 
定义了两个测试函数,功能一致,函数sum_test1用aop装饰器修饰(这里装饰器没有任何功能操作),函数sum_test2没有装饰器修饰 。
看代码执行结果:
如何消除Python装饰器产生的副作用

文章插图
 
你会发现:被装饰器修饰的函数,属性内容发生了改变,sum_test1函数的__name__、__doc__等等属性值都变成了装饰器函数对应属性值,而没有装饰的sum_test2函数显示正常!
【如何消除Python装饰器产生的副作用】更大的问题了,被装饰器修饰的多个函数,其函数属性值都会变成装饰器函数内容,多个不同的函数,其属性值是相同的,这非常不利于调试,定位程序bug 。
以上就是装饰器产生的副作用!
如何消除装饰器的副作用使用functools模块提供 wraps和update_wrApper 方法能够修正函数内置属性值,消除装饰器副作用
update_wrapper 使用示例:
如何消除Python装饰器产生的副作用

文章插图
 
看代码执行结果:
如何消除Python装饰器产生的副作用

文章插图
 
wraps使用示例:
如何消除Python装饰器产生的副作用

文章插图
 
update_wrapper和wraps方法的功能是一样的,只不过wraps是使用partial()对update_wrapper进一步封装得到的,所以推荐使用wraps方法!
总结使用装饰器给我们带来高效的编程,但是装饰器会产生一个容易让人忽视的副作用:不利于调试,定位程序bug 。
使用functools模块提供 wraps和update_wrapper 方法,消除Python装饰器副作用;而且使用update_wrapper和wraps是一个好的编程习惯!




    推荐阅读