我正在研究裝飾類的裝飾器。它對於實例方法來說很好,但爲類方法提供了一個TypeError。代碼如下:裝飾類方法的錯誤
def deco_method(fn):
def wrapper(*arg, **kwarg):
"""
Function: Wrapper
"""
print "Calling function {}".format(fn.__name__)
print arg, kwarg
ret_val = fn(*arg, **kwarg)
print "Executed function {}".format(fn.__name__)
return ret_val
return wrapper
def clsdeco(cls):
attributes = cls.__dict__.keys()
for attribute in attributes:
# Do not decorate private methods
if '__' in attribute:
continue
# Get the method
value = getattr(cls, attribute)
if not hasattr(value, '__call__'):
continue
# CHeck if method is a class method or normal method and decoate accordingly
if value.im_self is None:# non class method
setattr(cls, attribute, deco_method(value))
elif value.im_self is cls: # CHeck if the method is class method
setattr(cls, attribute, classmethod(deco_method(value)))
else:
assert False
return cls # return decorated class
@clsdeco
class Person:
message = "Hi Man"
def __init__(self, first_name, last_name):
self.fname = first_name
self.lname = last_name
self.age = None
def get_name(self):
print "Name is '{} {}'".format(self.fname, self.lname)
@classmethod
def greet_person(cls):
print cls.message
p = Person('John', 'snow')
p.greet_person()
它給出了一個錯誤:
TypeError: greet_person() takes exactly 1 argument (2 given)
如果我刪除@clsdeco,它完美的罰款。
任何想法我在這裏失蹤?
謝謝!我沒有注意到getattr返回描述符。 「value = cls .__ dict __ [attribute] .__ func__」works。或者,我們也可以爲python 2.7創建「value = value.im_func」和「value = value .__ func__」[python 3] – Luminos
@Luminos:在Python 2.6中,他們爲'im_func'創建了'__func__'的alais,這會更便於攜帶 - 但我相信使用'cls .__ dict __ [attribute] .__ func__'已經可以在Python 2和Python 3中運行。 – martineau