Использование super()
, __init__()
и множественное наследование немного сложнее.
В обычном порядке вещей каждый метод вызывает super()
, при этом классы, которые наследуются только от object
, выполняют небольшую дополнительную работу, чтобы убедиться, что метод действительно существует: выглядеть примерно так:
>>> class Foo(object):
... def frob(self, arg):
... print "Foo.frob"
... if hasattr(super(Foo, self), 'frob'):
... super(Foo, self).frob(arg)
...
>>> class Bar(object):
... def frob(self, arg):
... print "Bar.frob"
... if hasattr(super(Bar, self), 'frob'):
... super(Bar, self).frob(arg)
...
>>> class Baz(Foo, Bar):
... def frob(self, arg):
... print "Baz.frob"
... super(Baz, self).frob(arg)
...
>>> b = Baz()
>>> b.frob(1)
Baz.frob
Foo.frob
Bar.frob
>>>
Но когда вы пытаетесь сделать нечто похожее на метод, который есть у object
, все становится немного рискованным; object.__init__
не принимает аргументы, поэтому единственный безопасный способ его использования - вызвать super().__init__()
без аргументов, поскольку этот вызов может быть обработан object.__init__
. Но тогда он может не обрабатываться object.__init__
, а вместо этого обрабатываться классом в другом месте в графе наследования. Таким образом, любой класс, который определяет __init__
в иерархии множественного наследования, должен быть подготовлен для вызова с без аргументов .
Один из способов справиться с этим - никогда не использовать аргументы в __init__()
. Выполните минимальную инициализацию и полагайтесь на настройку свойств или использование других средств для настройки нового объекта перед использованием. Это довольно неприятно.
Другой способ - использовать только ключевые аргументы, например, def __init__(self, **keywords):
, и всегда удалять аргументы, которые применяются к данному конструктору. Это основанная на надежде стратегия, вы надеетесь , что все ключевые слова будут использованы до того, как контроль достигнет object.__init__
.
Третий способ - определить суперкласс для всех множественных наследуемых баз, который сам по себе определенным образом определяет __init__
и не вызывает super().__init__
(object.__init__
не оп в любом случае). Это означает, что вы можете быть уверены , что этот метод всегда вызывается последним, и вы можете делать все, что захотите, с вашими аргументами.