__init__ в наследовании классов Python
День добрый, искал похожие темы, но не нашел в них ответа на свой вопрос. Книга из которой пример (Эрик Метиз - Изучаем Python) внятного объяснения тоже нет, либо я не понимаю его.
Итак, классический пример: есть класс родитель и его метод:
class Car():
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
long_name = (f"\nЭто ваша машина: {self.make} {self.model} {self.year}")
return long_name.title()
И есть класс наследник:
class Electric_Car(Car):
def __init__(self, make, model, year, price):
self.price = price
super().__init__(make, model, year)
self.battery_size = 75
def get_descriptive_name(self):
super().get_descriptive_name()
long_name = (f"\nЭто ваша машина: {self.make} {self.model} {self.year} {self.price}")
return long_name.title()
Собственно вопросы:
Комментарий в книге к строке def
__init__(self, make, model, year):класса Electric_Car следующий - "Метод__init__()получает информацию, необходимую для создания экземпляра Car ."Мне он ни о чем не говорит, пытаясь изменить эти параметры я получаю ошибку. Но я могу добавить в конец списка новый параметр и прописать (например
self.price = price) под этой строкой. Почему тогда первые 3 параметра нельзя изменить?В строке
super().__init__(make, model, year)я не могу не добавить ни изменить параметры, т.к будет ошибка. Так как это параметры класса родителя?Если я изменю любой параметр строки
def __init__(self, make, model, year):то в строкеsuper().__init__(make, model, year)он будет подчеркнут красным, соответственно эти параметры связаны, зачем тогда дублирование строк?Я захотел переопределить метод
def get_descriptive_name(self), добавлением в него строкиsuper().get_descriptive_name()а так же параметраself.priceв переменную, правильно ли это?
P.S Посоветуйте толковую книгу по Python где все более детально описывается.
Ответы (1 шт):
1, 2: Через super().__init__(...) вызывается __init__ родительского класса, в него нужно передать именно те параметры, который для __init__ родительского класса нужны. Можно, конечно, передать какие-то другие параметры, но работать не будет, или будет работать неправильно :)
Но я могу добавить в конец списка новый параметр и прописать...
- не обязательно в конец, можно в середину или в начало, главное чтобы при создании объекта передавались правильные значения в правильные параметры. Никакого правила, которое запрещает добавлять свои параметры в любое место, нет (кроме правила, что именованные параметры должны идти после позицонных). Но обычно чтобы не запутаться, лучше добавлять в конец.
3: это не дублирование. def __init__(...) - это объявление метода, а super().__init__(...) - это вызов метода вызов метода. Если метод не вызвать, то сам он не запустится. Если вызывать метода с другим количеством параметров, чем было объявлено, то в данном случае это будет ошибкой (могут быть конечно методы со значениями параметров по умолчанию и всякими *args, **kwargs, но в данном случае этого нет, поэтому количество параметров должно совпадать).
4: в данном случае переопределенный метод никак не использует значение, возвращаемое родительским методом, и родительский метод никак не меняет состояние объекта (или "внешнего мира"), поэтому (опять же, в данном случае) в вызове родительского метода нет особого смысла. В других случаях вызов родительского метода может быть необходим.