Программирование и IT
Python: ООП
Объектно ориентированное программирование — способ описывать задачу через объекты, у которых есть состояние и поведение. В Python его четыре обычных кирпича устроены проще, чем в Java или C++: наследование есть, private нет, а совместимость типов проверяется по поведению, а не по родословной.
В этой статье
Наследование: переиспользовать, а не копировать#
Класс-наследник получает все атрибуты и методы родителя и может добавить свои
или заменить существующие.
=
=
return
=
return +
=
# 150 Пётр
# True
super() обращается к следующему классу в цепочке наследования. Вызов
super().__init__(...) в конструкторе наследника обязателен, если родитель
что-то заполняет: без него у объекта просто не окажется полей, и падение
случится позже и не в том месте.
Проверять тип нужно через isinstance, а не type(x) == Employee: второе
даст False для наследника и сломает всю идею.
Полиморфизм и утиная типизация#
Полиморфизм здесь означает: одинаковый вызов, разный результат в зависимости
от класса объекта.
return
return
# гав мяу
Обрати внимание: Dog и Cat не связаны наследованием, и это не мешает.
Python не спрашивает, какого объект класса, — он проверяет, есть ли у объекта
нужный метод. Такой подход называют утиной типизацией: если объект крякает
как утка, для кода он утка. Поэтому чаще всего общий базовый класс не нужен
вообще.
Когда общий контракт всё-таки хочется зафиксировать, берут модуль abc:
...
=
return ** 2
# 16
# TypeError: Can't instantiate abstract class Shape without an implementation
# for abstract method 'area'
Инкапсуляция: подчёркивания вместо private#
Ключевых слов private и protected в языке нет. Есть соглашение и один
технический приём.
name— открытый атрибут, часть интерфейса._name— внутренний; трогать снаружи не следует, но язык не запрещает.__name— имя искажается: внутри классаAccountоно превращается в
_Account__name.
=
return
=
# 500
# 500 — «приватность» обходится одной строкой
= 0
# AttributeError: property 'balance' of 'Account' object has no setter
Двойное подчёркивание придумано не для защиты от программиста, а чтобы имя
случайно не перекрылось в наследнике. Настоящий способ ограничить доступ —
@property без сеттера: атрибут читается, но не присваивается.
Композиция вместо длинных иерархий#
Наследование связывает классы жёстко: изменение родителя ломает всех потомков.
Часто лучше сделать объект полем другого объекта.
return
= # машина ИМЕЕТ мотор
return
# мотор запущен
Простое правило выбора: «является» — наследование (Manager является
Employee), «имеет» — композиция (Car имеет Engine). Множественное
наследование в Python разрешено, порядок поиска методов виден в
Класс.__mro__, но в прикладном коде его почти всегда стоит избегать.
Практика: опиши базовый класс Shape с абстрактным area, наследников
Circle и Rect, сложи их в список и выведи общую площадь через
sum(s.area() for s in shapes). Устройство самого класса — в статье про
классы, а перебор без списка — в статье про
генераторы.
План по этапам
- Родитель и наследникНаписать базовый класс с двумя полями и наследника, который добавляет третье через super().__init__.
- Переопределить методЗаменить метод в наследнике и вызвать родительскую версию через super().
- Список разнородных объектовСложить объекты двух несвязанных классов в список и вызвать у всех одноимённый метод.
- Зафиксировать контрактСделать базовый класс через abc и убедиться, что создать его напрямую нельзя.
- Переписать на композициюВзять иерархию из трёх уровней и заменить один уровень полем-объектом.
Начать изучать эту тему у себя
План ляжет в твой репозиторий: отмечай этапы, веди конспект — история изменений покажет, как ты продвинулся.
Проверь себя
1.Manager наследует Employee. Что вернёт isinstance(Manager(), Employee)?
2.У Employee.pay() возвращается 100, у Manager.pay() — super().pay() + 50. Что вернёт Manager().pay()?
3.Внутри класса Account атрибут объявлен как self.__balance. Под каким именем он доступен снаружи?
4.Какое отношение лучше описать композицией, а не наследованием: «Car имеет Engine» или «Manager является Employee»?
Источники
-
Классы и наследование в учебнике PythonРазделы Inheritance и Multiple Inheritanceбесплатно
-
Модуль abc — абстрактные классыABC и abstractmethod с примерамибесплатно
-
StepikБесплатные курсы по Python, включая ООПбесплатно
Было полезно?