大家都知道裝飾器是乙個很著名的設計模式,經常被用於aop(面向切面程式設計)的場景,較為經典的有插入日誌,效能測試,事務處理,web許可權校驗, cache等。
python語言本身提供了裝飾器語法(@),典型的裝飾器實現如下:
deffunction
():pass
@實際上是python2.4才提出的語法糖,針對python2.4以前的版本有另一種等價的實現:
deffunction
():pass
function=(
function
)函式包裝器 - 經典實現
def(
):def
(*args,**
kwargs
):return
(*args,**
kwargs
)return
deffunction
():pass
類包裝器 - 易於理解
class
(object
):def
__init__
(self,):
self.=
def__call__
(self,*
args,**
kwargs
):return
self.(*
args,**
kwargs
)def
function
():pass
當我們談到乙個函式時,通常希望這個函式的屬性像其文件上描述的那樣,是被明確定義的,例如__name__ 和__doc__ 。
針對某個函式應用裝飾器時,這個函式的屬性就會發生變化,但這並不是我們所期望的。
def(
):def
(*args,**
kwargs
):return
(*args,**
kwargs
)return
deffunction
():pass
>>>
(function
.__name__
)python標準庫提供了functools.wraps() ,來解決這個問題。
import
functools
def(
):@functools
.wraps()
def(*
args,**
kwargs
):return
(*args,**
kwargs
)return
deffunction
():pass
>>>
(function
.__name__
)function
然而,當我們想要獲取被包裝函式的引數(argument )或源**(source code)時,同樣不能得到我們想要的結果。
import
inspect
def(
):...
deffunction
(arg1
,arg2
):pass
>>>
(inspect
.getargspec
(function
))argspec
(args
=,varargs
='args'
,keywords
='kwargs'
,defaults
=none
)>>>
(inspect
.getsource
(function
))@functools
.wraps()
def(*
args,**
kwargs
):return
(*args,**
kwargs
)class
class
(object
):@classmethod
defcmethod
(cls
):pass
traceback
(most recent call
last
):file"",
line 1,
infile"",
line 3,
inclass
file"",
line 2,
infile
".../functools.py"
,line 33,
insetattr(,
attr
,getattr(,
attr
))attributeerror
:'classmethod'
object
has
noattribute
'__module__'
然而,在python3下執行,另乙個問題出現了:
class
class
(object
):@classmethod
defcmethod
(cls
):pass
>>>
class
.cmethod
()traceback
(most recent call
last
):file
"classmethod.py"
,line 15,
inclass
.cmethod
()file
"classmethod.py"
,line 6,
inreturn
(*args,**
kwargs
)typeerror
:'classmethod'
object
isnot
callable
這是因為包裝器認定被包裝的函式(@classmethod )是可以直接被呼叫的,但事實並不一定是這樣的。被包裝的函式實際上可能是描述符(descriptor ),意味著為了使其可呼叫,該函式(描述符)必須被正確地繫結到某個例項上。關於描述符的定義,可以參考
儘管大家實現裝飾器所用的方法通常都很簡單,但這並不意味著它們一定是正確的並且始終能正常工作。
如同上面我們所看到的,functools.wraps() 可以幫我們解決__name__ 和__doc__ 的問題,但對於獲取函式的引數(argument)或源**( source code )則束手無策。
以上問題,wrapt都可以幫忙解決,詳細用法可參考其官方文件:
Python 裝飾器使用過程中的誤區
大家都知道裝飾器是乙個很著名的設計模式,經常被用於aop 面向切面程式設計 的場景,較為經典的有插入日誌,效能測試,事務處理,web許可權校驗,cache等。python語言本身提供了裝飾器語法 典型的裝飾器實現如下 def function pass 實際上是python2.4才提出的語法糖,針對...
python使用過程中問題
1.檢視python支援的 whl格式 在cmd輸入python 或者 python3.6 import pip print pip.pep425tags.get supported 2.在修改python.exe為python36.exe 任何重新命名 後,pip會報錯 fatal error i...
element ui dialog使用過程中的坑
場景一 我們將dialog寫成乙個可復用的公共元件用於顯示不同內容 如 操作中的修改或新增的彈窗 之後發現dialog的遮罩將彈出層 點選修改或新增後理應由乙個彈窗顯示出來 都蓋住了,而我想要的效果是遮罩只遮住舊的視窗,而當前視窗應該完全顯示 注 是使用easyui的panel和window來包裹的...