我想創建一個Python 類裝飾器(*),它將能夠無縫地包裝類可能具有的所有方法類型:實例,類和靜態。如何創建一個能夠包裝實例,類和靜態方法的Python類裝飾器?
這是我對現在的代碼,與打破它註釋的部分:
def wrapItUp(method):
def wrapped(*args, **kwargs):
print "This method call was wrapped!"
return method(*args, **kwargs)
return wrapped
dundersICareAbout = ["__init__", "__str__", "__repr__"]#, "__new__"]
def doICareAboutThisOne(cls, methodName):
return (callable(getattr(cls, methodName))
and (not (methodName.startswith("__") and methodName.endswith("__"))
or methodName in dundersICareAbout))
def classDeco(cls):
myCallables = ((aname, getattr(cls, aname)) for aname in dir(cls) if doICareAboutThisOne(cls, aname))
for name, call in myCallables:
print "*** Decorating: %s.%s(...)" % (cls.__name__, name)
setattr(cls, name, wrapItUp(call))
return cls
@classDeco
class SomeClass(object):
def instanceMethod(self, p):
print "instanceMethod: p =", p
@classmethod
def classMethod(cls, p):
print "classMethod: p =", p
@staticmethod
def staticMethod(p):
print "staticMethod: p =", p
instance = SomeClass()
instance.instanceMethod(1)
#SomeClass.classMethod(2)
#instance.classMethod(2)
#SomeClass.staticMethod(3)
#instance.staticMethod(3)
我有兩個問題想使這項工作:
- 當遍歷所有可以調用,我怎麼知道它是一個實例,類還是靜態類型?
- 如何使用正確調用的正確包裝版本覆蓋該方法,併爲每種情況正確調用?
目前,該代碼會生成不同TypeError
小號根據什麼評論片段是未加註釋,如:
TypeError: unbound method wrapped() must be called with SomeClass instance as first argument (got int instance instead)
TypeError: classMethod() takes exactly 2 arguments (3 given)
(*):同問題要簡單得多,如果你是decorating the methods directly。
看到不同的開發人員如何處理這個相同的,複雜的問題將會很有趣。 – wberry
@wberry:是的,我已經閱讀了當前的答案,並且發現很難選擇「正確」的答案。 – Chuim