裝飾器給我們帶來高效的編程,但也會產(chǎn)生一些問題,而這些問題又容易被我們大家忽視。
裝飾器產(chǎn)生的副作用
在Python世界里,一切皆對象,所以函數(shù)也是對象,函數(shù)有一些內(nèi)置屬性,例如:__name__、 __module__ 、__doc__ 和__dict__等。
如果使用裝飾器修飾函數(shù),那么函數(shù)的內(nèi)置屬性值會發(fā)生變化,這將不利于調(diào)試,定位bug位置,這就是裝飾器產(chǎn)生的副作用!
結(jié)合示例了解裝飾器的副作用:

定義了兩個測試函數(shù),功能一致,函數(shù)sum_test1用aop裝飾器修飾(這里裝飾器沒有任何功能操作),函數(shù)sum_test2沒有裝飾器修飾。
看代碼執(zhí)行結(jié)果:

你會發(fā)現(xiàn):被裝飾器修飾的函數(shù),屬性內(nèi)容發(fā)生了改變,sum_test1函數(shù)的__name__、__doc__等等屬性值都變成了裝飾器函數(shù)對應(yīng)屬性值,而沒有裝飾的sum_test2函數(shù)顯示正常!
更大的問題了,被裝飾器修飾的多個函數(shù),其函數(shù)屬性值都會變成裝飾器函數(shù)內(nèi)容,多個不同的函數(shù),其屬性值是相同的,這非常不利于調(diào)試,定位程序bug。
以上就是裝飾器產(chǎn)生的副作用!
如何消除裝飾器的副作用
使用functools模塊提供 wraps和update_wrApper 方法能夠修正函數(shù)內(nèi)置屬性值,消除裝飾器副作用
update_wrapper 使用示例:

看代碼執(zhí)行結(jié)果:

wraps使用示例:

update_wrapper和wraps方法的功能是一樣的,只不過wraps是使用partial()對update_wrapper進一步封裝得到的,所以推薦使用wraps方法!
總結(jié)
使用裝飾器給我們帶來高效的編程,但是裝飾器會產(chǎn)生一個容易讓人忽視的副作用:不利于調(diào)試,定位程序bug。
使用functools模塊提供 wraps和update_wrapper 方法,消除Python裝飾器副作用;而且使用update_wrapper和wraps是一個好的編程習(xí)慣!