Глава 14 · Создаём объекты реального мира
Наследование
Когда один класс — это более частный случай другого, наследование позволяет не переписывать общее поведение заново.
Строим класс на основе существующего
Если два класса имеют много общего, но один — более общее понятие, а другой — его частный случай, отношение между ними — IS-A («Кошка — это животное»). Для такого отношения в Python есть наследование:
nasledovanie.py
class Zhivotnoe:
def __init__(self, klichka):
self.klichka = klichka
def predstavitsya(self):
print(f"Я {self.klichka}")
class Sobaka(Zhivotnoe): # Sobaka — это Zhivotnoe
def zvuk(self):
return "Гав!"
class Koshka(Zhivotnoe): # Koshka — это тоже Zhivotnoe
def zvuk(self):
return "Мяу!"
rex = Sobaka("Рекс")
rex.predstavitsya() # унаследовано от Zhivotnoe — работает без переопределения
print(rex.zvuk()) # своё, определено в Sobaka
Zhivotnoe
Sobaka
Koshka
Наследование — это переиспользование, а не обязанность
Sobaka получает predstavitsya() БЕСПЛАТНО, ничего не переписывая — в этом весь смысл. Но наследование оправдано только когда отношение реально IS-A. Если тянет унаследовать класс просто чтобы «одолжить» пару методов без настоящего родства понятий — это сигнал, что нужна композиция (раздел 14.13), а не наследование.Debug Lab 8: забыли вызвать super().__init__()
propushchennyj_super.py
class Zhivotnoe:
def __init__(self, klichka):
self.klichka = klichka
class Sobaka(Zhivotnoe):
def __init__(self, klichka, poroda):
self.poroda = poroda # klichka из Zhivotnoe не настроен!
rex = Sobaka("Рекс", "Дворняга")
print(rex.klichka)
Traceback (most recent call last):
File "propushchennyj_super.py", line 9, in
print(rex.klichka)
AttributeError: 'Sobaka' object has no attribute 'klichka'
Когда дочерний класс определяет СОБСТВЕННЫЙ __init__, он полностью ЗАМЕНЯЕТ родительский __init__ — родительский код настройки атрибутов сам по себе больше не выполняется. Чтобы получить и то, и другое, дочерний __init__ должен явно вызвать родительский — разберём как именно, в разделе 14.16.
Исправленный код
s_super.py
class Sobaka(Zhivotnoe):
def __init__(self, klichka, poroda):
super().__init__(klichka) # сначала настраиваем родительскую часть
self.poroda = poroda
Практика: наследование
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки