Допустим, у нас есть метакласс CallableWrappingMeta
, который обходит тело нового класса, оборачивая его методы классом, InstanceMethodWrapper
:
import types
class CallableWrappingMeta(type):
def __new__(mcls, name, bases, cls_dict):
for k, v in cls_dict.iteritems():
if isinstance(v, types.FunctionType):
cls_dict[k] = InstanceMethodWrapper(v)
return type.__new__(mcls, name, bases, cls_dict)
class InstanceMethodWrapper(object):
def __init__(self, method):
self.method = method
def __call__(self, *args, **kw):
print "InstanceMethodWrapper.__call__( %s, *%r, **%r )" % (self, args, kw)
return self.method(*args, **kw)
class Bar(object):
__metaclass__ = CallableWrappingMeta
def __init__(self):
print 'bar!'
Наша фиктивная оболочка просто печатает аргументы по мере их поступления. Но вы заметите кое-что бросающееся в глаза: метод не передается получателю объекта-экземпляра, поскольку, хотя InstanceMethodWrapper
и вызывается, он не рассматривается как функция для преобразования в метод экземпляра при создании класса (после того, как наш метакласс завершен).
Потенциальное решение - использовать декоратор вместо класса для переноса методов - эта функция станет методом экземпляра. Но в реальном мире InstanceMethodWrapper
гораздо сложнее: он предоставляет API и публикует события вызова метода. Класс более удобный (и более производительный, хотя это и не имеет большого значения).
Я тоже пробовал тупики. Подклассы types.MethodType
и types.UnboundMethodType
никуда не делись. Небольшой самоанализ, и кажется, что они происходят от type
. Поэтому я попытался использовать оба в качестве метакласса, но и там мне не повезло. Возможно, они имеют особые требования в качестве метакласса, но, похоже, на данный момент мы находимся на недокументированной территории.
Есть идеи?