Скажем, я хочу реализовать метакласс, который должен служить фабрикой классов. Но в отличие от конструктора type
, который принимает 3 аргумента, мой метакласс должен вызываться без каких-либо аргументов:
Cls1 = MyMeta()
Cls2 = MyMeta()
...
Для этой цели я определил пользовательский метод __new__
без параметров:
class MyMeta(type):
def __new__(cls):
return super().__new__(cls, 'MyCls', (), {})
Но проблема в том, что python автоматически вызывает метод __init__
с теми же аргументами, что и метод __new__
, поэтому попытка вызова MyMeta()
приводит к возникновению исключения:
TypeError: type.__init__() takes 1 or 3 arguments
Что имеет смысл, поскольку type
можно вызывать с 1 или 3 аргументами. Но как правильно это исправить? Я вижу 3 (4?) Варианта:
- Я мог бы добавить пустой метод
__init__
к своему метаклассу, но так как я не уверен, что type.__init__
делает что-то важное, это может быть не очень хорошая идея.
- Я мог бы реализовать
__init__
метод, который вызывает super().__init__(cls.__name__, cls.__bases__, vars(cls))
.
- Я мог бы использовать мета-метакласс и переопределить его метод
__call__
, вместо того, чтобы связываться с __new__
и __init__
.
- Бонусный вариант: Может, мне не стоит пытаться изменить подпись?
Итак, мой вопрос: верны ли 3 решения, которые я перечислил, или в них скрыты какие-то тонкие ошибки? Какое решение является лучшим (то есть наиболее правильным)?