我试图使用调用它们时使用的一个参数对类的类方法进行一些验证。
为此,我使用了一个装饰器,用于将装饰器应用于所需的方法,该方法将使用函数中的一个参数执行验证功能。
这一切都适用于基类(对于此示例,我将其称为Parent
)。
但是,如果我创建另一个继承Parent
的类,(对于此示例,我将其称为Child
),继承的装饰classmethod将不再正常运行。
cls
类的classmethod中的Child
参数不是Child
符合预期,而是Parent
。
采用以下示例
import inspect
def is_number(word):
if word.isdigit():
print('Validation passed')
else:
raise Exception('Validation failed')
class ClassDecorator(object):
def __init__(self, *args):
self.validators = args
def __decorateMethod(self):
def wrapped(method):
def wrapper(cls, word, *args, **kwargs):
for validator in self.validators:
validator(word)
return method(word, *args, **kwargs)
return wrapper
return wrapped
def __call__(self, cls):
for name, method in inspect.getmembers(cls):
if name == 'shout':
decoratedMethod = self.__decorateMethod()(method)
setattr(cls, name, classmethod(decoratedMethod))
return cls
@ClassDecorator(is_number)
class Parent(object):
@classmethod
def shout(cls, word):
print('{} is shouting {}'.format(cls, word))
@classmethod
def say(cls):
print('{} is talking'.format(cls))
class Child(Parent):
pass
Parent.shout('123')
Child.shout('321')
将导致以下输出:
Validation passed
<class '__main__.Parent'> is shouting 123
Validation passed
<class '__main__.Parent'> is shouting 321
我的问题是:
Child
调用Parent
的类方法作为cls P.S。:我已经在Python 2.7.10和Python 3.5.2上尝试了这个并且已经有了相同的行为
答案 0 :(得分:6)
您正在装饰绑定类方法;正是这个对象持有Parent
并在调用时将其传递给原始shout
函数; <{1}}方法中绑定的任何cls
都不会被传入和忽略。
首先打开classmethods,你可以使用wrapper()
属性访问底层函数对象:
__func__
您现在必须考虑到您的包装器也在处理未绑定的函数,因此传递def __call__(self, cls):
for name, method in inspect.getmembers(cls):
if name == 'shout':
decoratedMethod = self.__decorateMethod()(method.__func__)
setattr(cls, name, classmethod(decoratedMethod))
return cls
参数或手动绑定:
cls