Должен ли init () вызывать init () родительского класса?
я использовал это в Objective-C у меня есть эта конструкция:
- (void)init {
if (self = [super init]) {
// init class
}
return self;
}
должен ли Python также вызывать реализацию родительского класса для __init__?
class NewClass(SomeOtherClass):
def __init__(self):
SomeOtherClass.__init__(self)
# init class
это также верно / ложно для __new__() и __del__()?
Edit: есть очень похожий вопрос: наследование и переопределение __init__ в Python
6 ответов:
в Python, вызывая супер-класс'
__init__не является обязательным. Если вы его вызываете, то также необязательно использоватьsuperидентификатор, или явное имя суперкласса:object.__init__(self)в случае объекта, вызов супер метода не является строго необходимым, так как супер метод пуст. То же самое для
__del__.ОТО, для
__new__, вы действительно должны вызвать метод super и использовать его возврат в качестве вновь созданного объекта-если вы явно хочу вернуть что-то другое.
Если вам нужно что-то из супер
__init__должно быть сделано в дополнение к тому, что делается в текущем классе__init__,вы должны вызвать его сами, так как это не произойдет автоматически. Но если вам ничего не нужно от супер__init__,нет необходимости называть его. Пример:>>> class C(object): def __init__(self): self.b = 1 >>> class D(C): def __init__(self): super().__init__() # in Python 2 use super(D, self).__init__() self.a = 1 >>> class E(C): def __init__(self): self.a = 1 >>> d = D() >>> d.a 1 >>> d.b # This works because of the call to super's init 1 >>> e = E() >>> e.a 1 >>> e.b # This is going to fail since nothing in E initializes b... Traceback (most recent call last): File "<pyshell#70>", line 1, in <module> e.b # This is going to fail since nothing in E initializes b... AttributeError: 'E' object has no attribute 'b'
__del__то же самое, (но будьте осторожны, полагаясь на__del__для завершения-рассмотрите возможность сделать это через оператор with вместо этого).Я редко использую
__new__.Я делаю все инициализация в__init__.
в ответе Анона:
"Если вам нужно что-то из супер__init__должно быть сделано в дополнение к тому, что делается в текущем классе__init__, вы должны назвать это сами, так как это не произойдет автоматически"это невероятно:он формулирует ровно противоположное принципу наследования.
это не "что-то из супер
__init__(...) не будет автоматически", это то, что это произойдет автоматически, но это не происходит, потому что базовый класс'__init__исключен по определению производной-клас__init__тогда зачем определять derived_class'
__init__, поскольку он переопределяет то, что нацелено на то, когда кто-то прибегает к наследованию ??это потому, что нужно определить то, что не сделано в базовом классе
__init__, и единственная возможность получить это, чтобы положить его выполнение в производном классе' .
Другими словами,нужно что-то в базовый класс' к тому, что будет автоматически сделано в базе-classe'__init__Если этот последний не был исключен.
А не наоборот.
тогда проблема в том, что нужные инструкции присутствуют в базовом классе'
__init__больше не активируются в момент создания экземпляра. Чтобы компенсировать это инактивация, требуется что-то особенное: явный вызов базового класса'__init__, чтобы сохранить, не добавляя, инициализация выполняется базовым классом'__init__. Это именно то, что сказано в официальном документе:переопределяющий метод в производном классе может на самом деле хотеть продлить вместо того, чтобы просто заменить метод базового класса С тем же именем. Существует простой способ прямого вызова метода базового класса: просто вызовите BaseClassName.methodname(self, arguments).
http://docs.python.org/tutorial/classes.html#inheritanceвот и вся история:
когда цель состоит в том, чтобы сохранить инициализацию, выполняемую базовым классом, то есть чистое наследование, ничего особенного не требуется, нужно просто избегать определения
__init__функция в производном классекогда цель состоит в том, чтобы заменить инициализация выполняется базовым классом,
__init__должен быть определен в производном классекогда целью является добавление процессов к инициализации, выполняемой базовым классом, производный класс'
__init__должен быть определен, содержащий явный вызов базового класса__init__
что я чувствую удивительным в посте Анона, так это не только то, что он выражает противоположность теории наследования, но и то, что то, что было 5 парней, проходящих мимо этого, не поворачивая головы, и, кроме того, никто не реагировал за 2 года в теме, интересную тему которой нужно читать относительно часто.
Edit: (после смены кода)
Мы не можем сказать вам, нужно ли вам звонить вашим родителям__init__(или любая другая функция). Наследование, очевидно, будет работать без такого вызова. Все зависит от логики вашего кода: например, если все ваши__init__делается в родительском классе, вы можете просто пропустить дочерний класс__init__в целом.рассмотрим следующий пример:
>>> class A: def __init__(self, val): self.a = val >>> class B(A): pass >>> class C(A): def __init__(self, val): A.__init__(self, val) self.a += val >>> A(4).a 4 >>> B(5).a 5 >>> C(6).a 12
там нет жесткого и быстрого правила. Документация для класса должна указывать, должны ли подклассы вызывать метод суперкласса. Иногда вы хотите полностью заменить поведение суперкласса, а в другое время увеличить его - т. е. вызвать свой собственный код до и/или после вызова суперкласса.
обновление: та же основная логика применяется к любому вызову метода. Конструкторы иногда нуждаются в особом рассмотрении (поскольку они часто устанавливают состояние, которое определяет поведение) и деструкторы, потому что они параллельные конструкторы (например, при распределении ресурсов, например, соединения с базой данных). Но то же самое может относиться, скажем, к
render()метод виджета.уточнения: что такое OPP? Вы имеете в виду ООП? Нет - подкласс часто должен знать что-то о дизайне суперкласса. Не внутренние детали реализации-но основной контракт, который суперкласс имеет со своими клиентами (используя классы). Это не нарушает принципы ООП в любом случае. Вот почему
protectedявляется допустимым понятием в ООП в целом (хотя, конечно, в Python).
ИМО, вы должны назвать его. Если ваш суперкласс
object, вы не должны, но в других случаях я думаю, что это исключительное не называть его. Как уже ответили другие, это очень удобно, если ваш класс даже не придется переопределить__init__себя, например, когда у него нет (дополнительного) внутреннего состояния для инициализации.
Comments