ООП: классы, наследование и полиморфизм на примере Python

ООП: классы, наследование и полиморфизм на примере Python

Данные на октябрь 2026, Python 3.13Опубликовано 23 июня 2025Обновлено 28 июля 20267 мин чтения
Форма-штамп выдаёт ряд одинаковых брусков на конвейере
Коротко
  • ООП строит программу из объектов: каждый хранит данные и умеет выполнять действия над ними.
  • Класс — шаблон, объект — его экземпляр; наследование переиспользует код, полиморфизм позволяет вызывать одно и то же по-разному.
  • В Python нет по-настоящему закрытых атрибутов: подчёркивание в начале имени — соглашение.
  • Классы нужны не всегда: для коротких скриптов часто хватает функций и словарей.
Содержание11 разделов ▾
  1. Зачем нужны классы и объекты
  2. Класс и объект в Python
  3. Инкапсуляция
  4. Наследование
  5. Полиморфизм
  6. Абстрактный класс
  7. Наследование или композиция
  8. Когда обойтись без классов
  9. Условия и ограничения
  10. Частые ошибки
  11. Короткий вывод

Объектно-ориентированное программирование (ООП) — это способ писать программу как набор объектов: каждый объект хранит свои данные и умеет выполнять действия над ними. Статья для тех, кто знает в Python переменные, функции и списки. Вы напишете три класса и увидите на запускаемом примере, что такое наследование и полиморфизм.

Определения сверены с официальным учебником Python и Википедией. Код проверен запуском на Python 3.13. Данные на октябрь 2026 года.

Зачем нужны классы и объекты

Представьте, что нужно считать площади разных фигур. Без классов можно хранить фигуру в словаре и написать функцию с цепочкой if:

Python
import math

def площадь(фигура):
    if фигура["вид"] == "круг":
        return math.pi * фигура["r"] ** 2
    elif фигура["вид"] == "прямоугольник":
        return фигура["a"] * фигура["b"]
    raise ValueError("неизвестная фигура")

print(площадь({"вид": "круг", "r": 2}))
print(площадь({"вид": "прямоугольник", "a": 3, "b": 4}))
Текст
12.566370614359172
12

Это работает, пока фигур две. Когда появится третья, придётся лезть в функцию и добавлять ещё одну ветку. С десятью фигурами функция превратится в длинную цепочку, в которой легко ошибиться. Классы решают эту задачу иначе: каждая фигура знает, как посчитать свою площадь.

Класс и объект в Python

Учебник Python определяет классы как средство связать данные и функциональность вместе. Создание нового класса создаёт новый тип объектов, и можно делать экземпляры этого типа. У каждого экземпляра могут быть атрибуты, в которых хранится состояние, и методы, которые это состояние изменяют.

Python
import math

class Круг:
    def __init__(self, r):
        self.r = r

    def площадь(self):
        return math.pi * self.r ** 2

к = Круг(2)
print(к.r, round(к.площадь(), 2))
Текст
2 12.57

Метод __init__ вызывается при создании объекта и задаёт начальные значения. Первый параметр каждого метода, по соглашению self, — это сам объект: через него метод обращается к его данным. Вызывая Круг(2), мы создаём объект с радиусом 2, а запись к.площадь() вызывает метод у этого объекта.

Инкапсуляция

Инкапсуляция означает, что данные и действия над ними собраны в одном месте, а детали можно не показывать снаружи. В классе Круг радиус и расчёт площади лежат рядом, и пользователю класса не нужно знать формулу.

Наследование

Наследование позволяет создать новый класс на основе существующего. Учебник показывает синтаксис class Производный(Базовый). Производный класс получает атрибуты и методы базового и может переопределить их. Обратиться к базовому классу из производного можно через super().

Сделаем общий класс Фигура и два наследника.

Python
import math

class Фигура:
    def __init__(self, название):
        self.название = название

    def площадь(self):
        raise NotImplementedError("в наследнике нужно переопределить площадь()")

    def описание(self):
        return f"{self.название}: площадь {self.площадь():.2f}"

class Круг(Фигура):
    def __init__(self, r):
        super().__init__("круг")
        self.r = r

    def площадь(self):
        return math.pi * self.r ** 2

class Прямоугольник(Фигура):
    def __init__(self, a, b):
        super().__init__("прямоугольник")
        self.a, self.b = a, b

    def площадь(self):
        return self.a * self.b

class Квадрат(Прямоугольник):
    def __init__(self, сторона):
        super().__init__(сторона, сторона)
        self.название = "квадрат"

Метод описание написан один раз в базовом классе, а работает для всех наследников. Квадрат наследуется от Прямоугольника и вообще не определяет площадь: он берёт её у родителя.

Полиморфизм

Полиморфизм здесь выглядит так: мы вызываем одно и то же действие у объектов разных классов, а каждый выполняет его по-своему.

Python
фигуры = [Круг(2), Прямоугольник(3, 4), Квадрат(5)]
for ф in фигуры:
    print(ф.описание())

print(isinstance(фигуры[2], Прямоугольник), isinstance(фигуры[2], Фигура), isinstance(фигуры[0], Прямоугольник))

try:
    Фигура("абстрактная").описание()
except NotImplementedError as e:
    print("Ошибка:", e)
Текст
круг: площадь 12.57
прямоугольник: площадь 12.00
квадрат: площадь 25.00
True True False
Ошибка: в наследнике нужно переопределить площадь()

Цикл не проверяет, какая перед ним фигура. Чтобы добавить новую фигуру, достаточно написать ещё один класс: код цикла и метод описание не меняются. Функция isinstance из документации проверяет, что объект принадлежит классу или его наследнику: квадрат одновременно Прямоугольник и Фигура, но не наоборот. Исключение NotImplementedError напоминает, что у «общей» фигуры площади нет: её должен определить наследник.

Абстрактный класс

Чтобы запретить создавать «общую» фигуру совсем, в Python есть модуль abc. Документация описывает его как инфраструктуру для абстрактных базовых классов. Для начала достаточно знать, что такой класс нельзя создать напрямую, а наследники обязаны реализовать нужные методы. Подробности — в документации модуля.

Наследование или композиция

Наследование выражает отношение «является»: квадрат является прямоугольником. Композиция выражает отношение «имеет»: автомобиль имеет двигатель.

Python
class Двигатель:
    def запустить(self):
        return "двигатель работает"

class Автомобиль:
    def __init__(self):
        self.двигатель = Двигатель()

    def поехать(self):
        return self.двигатель.запустить() + ", едем"

print(Автомобиль().поехать())
Текст
двигатель работает, едем

Автомобиль не наследуется от двигателя, а содержит его внутри.

СитуацияПодход
Один объект является частным случаем другогонаследование
Один объект состоит из других или использует ихкомпозиция
Наследование приводит к цепочке из нескольких уровнейподумайте о композиции

Когда обойтись без классов

Классы не обязательны. Первый пример этой статьи обошёлся без классов, а Википедия отмечает, что ООП нельзя считать лучшей парадигмой для всех задач.

ЗадачаЧем обойтись
Короткий скрипт, несколько шаговфункции
Набор данных без поведениясловарь или dataclass
Данные и действия над ними идут вместе, видов несколькокласс

Модуль dataclasses из документации автоматически добавляет в класс служебные методы вроде __init__ и __repr__:

Python
from dataclasses import dataclass

@dataclass
class Точка:
    x: float
    y: float

print(Точка(1, 2))
print(Точка(1, 2) == Точка(1, 2))
Текст
Точка(x=1, y=2)
True

Условия и ограничения

Версия
Python 3.13, октябрь 2026 — код проверен запуском; ссылки на документацию ведут на актуальную версию учебника.
Язык
Примеры на Python — в C++, Java и C# синтаксис и правила видимости отличаются, идея та же.
Уровень
Без сложных тем — множественное наследование, метаклассы и свойства в статье не разбираются.
Данные
Учебные примеры — фигуры с небольшими числами, без файлов и сети.

Частые ошибки

  • Забывают self в определении метода или при обращении к атрибуту.
  • Хранят изменяемые данные в атрибуте класса вместо атрибута объекта (см. ниже).
  • Строят цепочки наследования из пяти-шести уровней, где проще композиция.
  • Наследуют, когда нет отношения «является».
  • Путают класс и объект: Круг — шаблон, Круг(2) — экземпляр.

Про изменяемый атрибут класса. Если список создан в теле класса, он общий для всех объектов:

Python
class Корзина:
    товары = []
    def добавить(self, т):
        self.товары.append(т)

a, b = Корзина(), Корзина()
a.добавить("хлеб")
print(b.товары)
Текст
['хлеб']

Хлеб оказался в корзине b, хотя добавляли его в a. Правильно создавать список в __init__: self.товары = []. Тогда у каждого объекта свой список.

Короткий вывод

ООП собирает данные и действия над ними в объекты, а классы служат шаблонами для этих объектов. Наследование помогает не повторять код, полиморфизм позволяет работать с разными объектами одинаково. Если задача небольшая, хватит функций и словарей, а класс стоит заводить тогда, когда он упрощает код.

Источники

  1. Python Docs: The Python Tutorial, 9. Classes↗ docs.python.org
  2. Python Docs: abc — Abstract Base Classes↗ docs.python.org
  3. Python Docs: dataclasses — Data Classes↗ docs.python.org
  4. Википедия: Объектно-ориентированное программирование↗ ru.wikipedia.org
  5. Википедия: Наследование (программирование)↗ ru.wikipedia.org
  6. Википедия: Полиморфизм (информатика)↗ ru.wikipedia.org
  7. Яндекс Образование: Основы Python (хендбук)↗ education.yandex.ru

Частые вопросы

Что такое ООП простыми словами?

ООП — это способ писать программу как набор объектов. Каждый объект хранит свои данные и умеет выполнять действия над ними. Например, объект «круг» знает свой радиус и умеет считать площадь. Объекты создают по шаблонам — классам. Документация Python описывает класс как способ связать данные и функциональность вместе: новый класс создаёт новый тип объектов.

Какие принципы у ООП?

Обычно называют инкапсуляцию, наследование и полиморфизм; часто добавляют абстракцию. Инкапсуляция объединяет данные и методы в одном объекте и скрывает детали. Наследование позволяет создать новый класс на основе существующего. Полиморфизм позволяет вызывать одинаковое действие у объектов разных классов, а каждый отвечает по-своему. Перечень в разных источниках немного различается, поэтому уточняйте у автора курса.

Чем класс отличается от объекта?

Класс — это шаблон, а объект — конкретный экземпляр, созданный по этому шаблону. Класс Круг описывает, что у круга есть радиус и площадь. Объект Круг(2) — один конкретный круг с радиусом 2. По одному классу можно создать сколько угодно объектов, и у каждого будут свои значения атрибутов. В Python сам класс тоже является объектом, но для начала достаточно различать шаблон и экземпляр.

Нужно ли ООП в Python?

Нет, Python позволяет писать программы и без классов, в том числе с одними функциями. Учебник Python говорит, что классы дают все стандартные возможности ООП, но ничто не мешает обойтись без них — первый пример этой статьи написан на функциях. Классы пригодятся, когда данные и действия над ними всегда идут вместе, а похожих сущностей несколько. ООП в Python вы увидите почти в любой библиотеке, поэтому понимать его полезно. Русскоязычный хендбук Яндекса «Основы Python» разбирает ООП в отдельной главе.

Где бесплатно изучить ООП на русском?

Подойдёт хендбук «Основы Python» на платформе Яндекс Образования: в нём есть отдельная глава про объектно-ориентированное программирование. По описанию авторов, специальные знания не нужны, достаточно школьной базы по математике, логике и информатике. Для терминов и истории есть русскоязычная статья Википедии. Официальный учебник Python с главой Classes написан на английском.

РедакцияМатериал подготовлен по источникам выше · 28 июля 2026