Python не выполняет неявных вызовов к __init__
методам суперкласса (ов) класса, но это возможно сделать автоматически.Одним из способов является определение метакласса для вашего смешанного класса (классов), который создает или расширяет метод __init__
смешанного класса, чтобы он вызывал все перечисленные функции базисов __init__
в порядке, в котором они были перечислены.
Второй способ - использовать декоратор класса, который показан в разделе Правка ниже.
Использование метакласса:
class APIBaseClassOne(object): # API class (can't be changed)
def __init__(self, *args, **kwargs):
print(' APIBaseClassOne.__init__()')
class SomeMixin(object):
def __init__(self, *args, **kwargs):
print(' SomeMixin.__init__()')
class MixedClassMeta(type):
def __new__(cls, name, bases, classdict):
classinit = classdict.get('__init__') # Possibly None.
# Define an __init__ function for the new class.
def __init__(self, *args, **kwargs):
# Call the __init__ functions of all the bases.
for base in type(self).__bases__:
base.__init__(self, *args, **kwargs)
# Also call any __init__ function that was in the new class.
if classinit:
classinit(self, *args, **kwargs)
# Add the local function to the new class.
classdict['__init__'] = __init__
return type.__new__(cls, name, bases, classdict)
class MixedClass(APIBaseClassOne, SomeMixin):
__metaclass__ = MixedClassMeta # important
# If exists, called after the __init__'s of all the direct bases.
def __init__(self, *args, **kwargs):
print(' MixedClass.__init__()')
print('MixedClass():')
MixedClass()
Вывод:
MixedClass():
APIBaseClassOne.__init__()
SomeMixin.__init__()
MixedClass.__init__()
Редактировать
Вот как выполнить то же самое с декоратором классов (требуется Python 2.6 +):
class APIBaseClassOne(object): # API class (can't be changed)
def __init__(self, *args, **kwargs):
print(' APIBaseClassOne.__init__()')
class SomeMixin(object):
def __init__(self, *args, **kwargs):
print(' SomeMixin.__init__()')
def mixedomatic(cls):
""" Mixed-in class decorator. """
classinit = cls.__dict__.get('__init__') # Possibly None.
# Define an __init__ function for the class.
def __init__(self, *args, **kwargs):
# Call the __init__ functions of all the bases.
for base in cls.__bases__:
base.__init__(self, *args, **kwargs)
# Also call any __init__ function that was in the class.
if classinit:
classinit(self, *args, **kwargs)
# Make the local function the class's __init__.
setattr(cls, '__init__', __init__)
return cls
@mixedomatic
class MixedClass(APIBaseClassOne, SomeMixin):
# If exists, called after the __init__'s of all the direct base classes.
def __init__(self, *args, **kwargs):
print(' MixedClass.__init__()')
print('MixedClass():')
MixedClass()
Примечания
Для Python <2.6 используйте <code>MixedClass = mixedomatic(MixedClass) после определения класса.
В Python 3 синтаксис для определения метаклассов отличаетсяпоэтому вместо:
class MixedClass(APIBaseClassOne, SomeMixin):
__metaclass__ = MixedClassMeta # important
, показанного выше, вам нужно будет использовать:
class MixedClass(APIBaseClassOne, SomeMixin, metaclass=MixedClassMeta):
Версия декоратора класса будет работать как есть в обеих версиях.