Ваши ExposedMethod
экземпляры ведут себя не как обычные методы экземпляров, а как статические методы - тот факт, что вы даете одному из них аргумент self
, указывает на то, что вы этого не знаете.Возможно, вам понадобится добавить метод __get__
в класс ExposedMethod
, чтобы сделать его дескриптором, точно так же как объекты функций - см. здесь для получения дополнительной информации о дескрипторах.
Но естьэто намного более простой способ, поскольку функции могут иметь атрибуты ...:
def ExposedMethod(registry=None):
def decorate(f):
f.registry = registry
return f
return decorate
и в декораторе class (проще, чем метакласс! требуется Python 2.6или лучше - в 2.5 или более ранних версиях вам нужно придерживаться метакласса или явно вызывать его после оператора class
, хотя первая часть ответа и функциональность приведенного ниже кода все еще в порядке):
def RegisterExposedMethods(cls):
for name, f in vars(cls).iteritems():
if not hasattr(f, 'registry'): continue
registry = f.registry
if registry is None:
registry = cls.registry
registry.register(name, cls.__name__)
return cls
Таким образом, вы можете сделать:
@RegisterExposedMethods
class MyClass (object):
@ExposeMethod(WorkerFunctionRegistry)
def myCoolExposedMethod (self):
pass
и тому подобное.Это легко расширить, позволяя открытому методу иметь несколько реестров, получить реестр по умолчанию в другом месте, чем из класса (например, в декораторе класса, если это работает лучше для вас) и позволяют избежатьзапутаться в метаклассах без потери функциональности.Действительно, именно поэтому в Python 2.6 были введены декораторы классов: они могут заменить 90% практического использования метаклассов и на намного проще, чем пользовательские метаклассы.