Я пытаюсь внедрить часть своего собственного кода в процесс построения класса SqlAlchemy. Пытаясь понять код, меня несколько смущает реализация метакласса. Вот соответствующие фрагменты:
По умолчанию "метакласс" SqlAlchemy:
class DeclarativeMeta(type):
def __init__(cls, classname, bases, dict_):
if '_decl_class_registry' in cls.__dict__:
return type.__init__(cls, classname, bases, dict_)
else:
_as_declarative(cls, classname, cls.__dict__)
return type.__init__(cls, classname, bases, dict_)
def __setattr__(cls, key, value):
_add_attribute(cls, key, value)
declarative_base
выполняется следующим образом:
def declarative_base(bind=None, metadata=None, mapper=None, cls=object,
name='Base', constructor=_declarative_constructor,
class_registry=None,
metaclass=DeclarativeMeta):
# some code which should not matter here
return metaclass(name, bases, class_dict)
Он используется следующим образом:
Base = declarative_base()
class SomeModel(Base):
pass
Теперь я получил свой собственный метакласс следующим образом:
class MyDeclarativeMeta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
result = DeclarativeMeta.__init__(cls, classname, bases, dict_)
print result
# here I would add my custom code, which does not work
return result
И используйте его следующим образом:
Base = declarative_base(metaclass=MyDeclarativeMeta)
Хорошо, теперь к моей проблеме:
-
print result
в моем собственном классе всегда печатаетNone
. - Кажется, что код работает!?
- Почему метакласс использует
__init__
, а не__new__
-
declarative_base
возвращает экземпляр этого класса. Не следует ли возвращать класс, имеющий атрибут__metaclass__
, имеющийMyDeclarativeMeta
как значение?
Так что мне интересно, почему код работает вообще. Поскольку люди SqlAlchemy, очевидно, знают, что они делают, я предполагаю, что я нахожусь на совершенно неправильном пути. Может ли кто-нибудь объяснить, что здесь происходит?