Ответ 1
super()
возвращает родительский объект в классах нового стиля:
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
B()
class A:
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
B() # output: hello
Во всех других языках, с которыми я работал, супер-конструктор вызывается неявно. Как можно вызвать его в Python? Я ожидал бы super(self)
но это не работает.
super()
возвращает родительский объект в классах нового стиля:
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
B()
В соответствии с другими ответами существует множество способов вызова методов суперкласса (включая конструктор), однако в Python-3.x процесс упрощен:
Python-2.x
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
Python-3.x
class A(object):
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
super().__init__()
super()
теперь эквивалентен super(<containing classname>, self)
в соответствии с документами.
С классами старого стиля Python 2.x это будет следующим:
class A:
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
A.__init__(self)
Один из способов - вызвать конструктор A и передать self
в качестве аргумента, например так:
class B(A):
def __init__(self):
A.__init__(self)
print "hello"
Преимущество этого стиля в том, что он очень понятен. Это называется инициализатором. Недостатком является то, что он не очень хорошо обрабатывает наследование в форме ромба, так как в итоге вы можете дважды вызвать инициализатор общего базового класса.
Другой способ - использовать super(), как показали другие. Для одиночного наследования это в основном то же самое, что позволить вам вызвать родительский инициализатор.
Однако super() немного сложнее и иногда может быть нелогичным в ситуациях множественного наследования. С другой стороны, super() может использоваться для обработки наследования в форме ромба. Если вы хотите узнать все о том, что делает super(), лучшее объяснение того, как работает super(), я нашел здесь (хотя я не обязательно поддерживаю мнения этой статьи).
Короткий ответ
super(DerivedClass, self).__init__()
Длинный ответ
Что делает super()
?
Он принимает указанное имя класса, находит его базовые классы (Python допускает множественное наследование) и ищет метод (в данном случае __init__
) в каждом из них слева направо. Как только он находит метод доступным, он вызывает его и завершает поиск.
Как мне вызвать init всех базовых классов?
Выше работает, если у вас есть только один базовый класс. Но Python допускает множественное наследование, и вы можете убедиться, что все базовые классы инициализированы правильно. Для этого у вас должен быть каждый вызов базового класса init:
class Base1:
def __init__():
super(Base1, self).__init__()
class Base2:
def __init__():
super(Base2, self).__init__()
class Derived(Base1, Base2):
def __init__():
super(Derived, self).__init__()
Что если я забуду вызвать init для супер?
Конструктор (__new__
) вызывается в цепочке (как в C++ и Java). После создания экземпляра вызывается только этот инициализатор экземпляра (__init__
) без какой-либо неявной цепочки для его суперкласса.
Просто добавьте пример с параметрами:
class B(A):
def __init__(self, x, y, z):
A.__init__(self, x, y)
Учитывая производный класс B, который требует определения переменных x, y, z, и суперкласс A, который требует определения x, y, вы можете вызвать статический метод init суперкласса A со ссылкой на текущий экземпляр подкласса (self) и затем списком ожидаемых аргументов.
Я использую следующую формулу, которая расширяет предыдущие ответы:
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(self.__class__, self).__init__()
B()
Таким образом, вам не нужно повторять имя класса в вызове super. Это может пригодиться, если вы кодируете большое количество классов и хотите сделать свой код в методах инициализатора независимым от имени класса.