Перейти к содержанию

232 уроков, 16 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 7 из 20 Средний 40 мин 140 XP

Наследование: расширяем классы

Наследование — способ расширять классы без переписывания: потомок получает всё от родителя, переопределяет и дополняет через super(). Родство проверяет isinstance.

Редакция Питоники

Классы из первых уроков живут поодиночке, но реальные сущности образуют семьи: собака — это животное, щенок — это собака; товар и его скидочная версия; пользователь и администратор. Наследование позволяет описать общее один раз в родителе, а в потомках — только отличия: это фундамент полиморфизма, о котором — через два урока. Синтаксис прост: class Dog(Animal) — «собака есть животное».

Родитель и потомок: Animal и Dog

Класс в скобках — родитель (базовый класс), новый — потомок (подкласс). Потомок получает всё: атрибуты и методы родителя работают, как будто вы написали их заново. Поверх унаследованного потомок добавляет своё.

потомок наследует и добавляет
class Animal:
    def __init__(self, name):
        self.name = name

    def sleep(self):
        print(f"{self.name} спит")

class Dog(Animal):
    def bark(self):
        print(f"{self.name} говорит: Гав!")

rex = Dog("Рекс")
rex.sleep()
rex.bark()
Вывод
Рекс спит
Рекс говорит: Гав!

Переопределение и super()

каждое животное — со своим голосом
class Animal:
    def __init__(self, name):
        self.name = name

    def voice(self):
        print(f"{self.name} издаёт звук")

class Cat(Animal):
    def voice(self):
        print(f"{self.name} говорит: Мяу")

class Cow(Animal):
    def voice(self):
        print(f"{self.name} говорит: Муу")

zoo = [Cat("Барсик"), Cow("Зорька"), Animal("Существо")]
for animal in zoo:
    animal.voice()
Вывод
Барсик говорит: Мяу
Зорька говорит: Муу
Существо издаёт звук
цепочка Animal — Dog — Puppy
class Animal:
    def __init__(self, name):
        self.name = name

    def voice(self):
        print(f"{self.name} издаёт звук")

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed

    def voice(self):
        super().voice()
        print("Гав-гав!")

class Puppy(Dog):
    def voice(self):
        super().voice()
        print("Тяв-тяв!")

puppy = Puppy("Бублик", "мопс")
puppy.voice()
print(puppy.name, puppy.breed)
Вывод
Бублик издаёт звук
Гав-гав!
Тяв-тяв!
Бублик мопс

super() означает «возьми ближайшую родительскую реализацию по цепочке наследования и продолжи с ней». В цепочке Animal — Dog — Puppy вызов super().voice() в щенке находит voice у собаки, а собачий super() — голос животного: поведение складывается этажами. Куда именно смотрит super() в сложных иерархиях — тема урока про MRO. А проверить родственные связи помогает isinstance — он отвечает True и для класса самого объекта, и для всех его родителей.

ПроверкаРезультатЧто проверяет
isinstance(rex, Puppy)Trueточный класс объекта
isinstance(rex, Dog)Trueкласс-родитель в цепочке
isinstance(rex, Animal)Trueвся цепочка наследования
issubclass(Puppy, Dog)Trueнаследование классов без экземпляра
isinstance видит всю цепочку
class Animal:
    pass

class Dog(Animal):
    pass

class Puppy(Dog):
    pass

rex = Puppy()

print(isinstance(rex, Puppy))
print(isinstance(rex, Dog))
print(isinstance(rex, Animal))
print(isinstance(rex, int))
Вывод
True
True
True
False
Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

class Animal:
    def __init__(self, name):
        self.name = name

    def voice(self):
        print("...")

class Dog(Animal):
    def voice(self):
        print("Гав!")

dog = Dog("Рекс")
dog.voice()
class Animal:
    def __init__(self, name):
        self.name = name

class Cat(Animal):
    def __init__(self, name, whiskers):
        super().__init__(name)
        self.whiskers = whiskers

cat = Cat("Барсик", 24)
print(cat.name, cat.whiskers)
class A:
    def hello(self):
        print("A")

class B(A):
    def hello(self):
        print("B")

class C(B):
    pass

obj = C()
obj.hello()
Проверь себя
0 / 6

1. Что даёт запись class Dog(Animal)?

2. Что значит переопределить метод?

3. Зачем в __init__ потомка вызывают super().__init__(name)?

4. isinstance(rex, Animal) при цепочке Animal — Dog — Puppy вернёт...

5. Сработает ли rex.sleep(), если sleep определён только в Animal?

6. Что делает super().voice() внутри Puppy.voice?

Карточки терминов
Запомнено: 0 / 7
Практика

Постройте цепочку Vehicle — Car. Vehicle хранит число колёс в __init__(self, wheels) и умеет describe(): печатает «Транспорт, колёс: N». Car наследует Vehicle: его __init__(self, model, wheels) вызывает super().__init__(wheels) и сохраняет model; describe() у Car сначала вызывает super().describe(), затем печатает «Автомобиль: модель». Создайте Car("Жигули", 4) и вызовите describe().

practice.py
Вопросы и ответы по уроку

Что такое наследование в Python простыми словами?

Это связь «является»: class Dog(Animal) означает «собака является животным». Потомок автоматически получает все атрибуты и методы родителя, добавляет свои и при необходимости переопределяет унаследованные. Общее поведение описывается один раз — в родителе.

Что делает super()?

Даёт доступ к реализации родителя из метода потомка. Чаще всего вызывается в __init__ потомка — super().__init__(...) настраивает родительскую часть объекта — и в переопределённых методах, когда нужно дополнить поведение, а не заменить его.

Чем переопределение отличается от расширения метода?

Переопределение (тот же def voice в потомке) заменяет родительскую версию полностью. Расширение — это переопределение с вызовом super().voice() внутри: сначала отрабатывает родитель, потом добавляется своё. Для сценария «сделай как родитель, плюс» выбирайте второе.

Урок 8: super() и MRO

Как проверить, что объект принадлежит классу или его потомкам?

Функцией isinstance(obj, Class): она вернёт True и для точного класса, и для любого родителя в цепочке — isinstance(rex, Animal) истинно для щенка. Наследование между классами без экземпляров проверяет issubclass(Puppy, Dog), а точный класс — type(rex) is Puppy.

Понравился урок? Сошлитесь на него

«super() означает «возьми ближайшую родительскую реализацию по цепочке наследования и продолжи с ней».»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.