См. Полный текст здесь
Рассмотрим случай, когда у нас есть простой метакласс, который генерирует метод __init__
для класса
class TestType(type):
def __new__(cls, cname, bases, attrs):
# Dynamically create the __init__ function
def init(self, message):
self.message = message
# Assign the created function as the __init__ method.
attrs['__init__'] = init
# Create the class.
return super().__new__(cls, cname, bases, attrs)
class Test(metaclass=TestType):
def get_message(self):
return self.message
Теперь этовсе хорошо и хорошо для использования
test = Test('hello')
assert test.get_message() == 'hello'
Но у нас есть проблемы при создании подклассов, потому что если вы хотите создать подкласс метода __init__
, то, конечно, происходит, что метод подклассов просто перезаписывается.
class SubTest(Test):
def __init__(self, first, second):
self.first = first
self.second = second
super().__init__(first + ' ' second)
subtest = SubTest('hello', 'there')
Это, очевидно, даст
TypeError: init() takes 2 positional arguments but 3 were given
. Единственный способ решить эту проблему - создать промежуточный класс в методе метакласса __new__
и сделать его основой для класса.мы создаем.Но я не могу заставить это работать, я пробовал что-то вроде этого
class TestType(type):
def __new__(cls, cname, bases, attrs):
# Dynamically create the __init__ function
def init(self, message):
self.message = message
# If the __init__ method is being subclassed
if '__init__' in attrs:
# Store the subclass __init__
sub_init = attrs.pop('__init__')
# Assign the created function as the __init__ method.
attrs['__init__'] = init
# Create an intermediate class to become the base.
interm_base = type(cname + 'Intermediate', bases, attrs)
# Add the intermediate class as our base.
bases = (interm_base,)
# Assign the subclass __init__ as the __init__ method.
attrs['__init__'] = sub_init
else:
# Assign the created function as the __init__ method.
attrs['__init__'] = init
# Create the class.
return super().__new__(cls, cname, bases, attrs)
Но это дает мне ошибку рекурсии
RecursionError: maximum recursion depth exceeded while calling a Python object