ООП на Python: концепции, принципы и примеры реализации
Программирование на Python допускает различные методологии, но в его основе лежит объектный подход, поэтому работать в стиле ООП на Python очень просто.
Если вам интересно, что думает об этой концепции сам ее создатель Алан Кэй, загляните сюда.
Язык Python – типичный представитель ООП-семейства, обладающий элегантной и мощной объектной моделью. В этом языке от объектов никуда не спрятаться (ведь даже числа являются ими), поэтому давайте разбираться, как это все реализовано.
Основы ООП на Python для начинающих
Классы
Создавать классы в Python очень просто:
Классы-родители перечисляются в скобках через запятую:
С реализацией наследования разберемся чуть позже.
Свойства классов устанавливаются с помощью простого присваивания:
Методы объявляются как простые функции:
Обратите внимание на первый аргумент – self – общепринятое имя для ссылки на объект, в контексте которого вызывается метод. Этот параметр обязателен и отличает метод класса от обычной функции.
Экземпляры классов
Инстанцировать класс в Python тоже очень просто:
Можно создавать разные инстансы одного класса с заранее заданными параметрами с помощью инициализатора (специальный метод __init__ ). Для примера возьмем класс Point (точка пространства), объекты которого должны иметь определенные координаты:
Подробнее о других специальных методах жизненного цикла объектов поговорим чуть ниже.
Динамическое изменение
Можно обойтись даже без определения атрибутов и методов:
Кажется, этот класс совершенно бесполезен? Отнюдь. Классы в Python могут динамически изменяться после определения:
Статические и классовые методы
Еще есть так называемые методы классов. Они аналогичны методам экземпляров, но выполняются не в контексте объекта, а в контексте самого класса (классы – это тоже объекты). Такие методы создаются с помощью декоратора @classmethod и требуют обязательную ссылку на класс ( cls ).
Статические и классовые методы доступны без инстанцирования.
Специальные методы
Жизненный цикл объекта
Это обсуждение на stackoverflow поможет лучше разобраться с инстанцированием классов.
Метод __new__ может быть очень полезен для решения ряда задач, например, создания иммутабельных объектов или реализации паттерна Синглтон:
На практике деструктор используется редко, в основном для тех ресурсов, которые требуют явного освобождения памяти при удалении объекта. Не следует совершать в нем сложные вычисления.
Объект как функция
Объект класса может имитировать стандартную функцию, то есть при желании его можно «вызвать» с параметрами. За эту возможность отвечает специальный метод __call__ :
Имитация контейнеров
Но для объектов вашего пользовательского класса это не пройдет:
Решить эту проблему поможет специальный метод __len__ :
Можно работать с объектом как с коллекцией значений, определив для него интерфейс классического списка с помощью специальных методов:
Имитация числовых типов
Ваши объекты могут участвовать в математических операциях, если у них определены специальные методы. Например, __mul__ позволяет умножать объект на число по определенной программистом логике:
Другие специальные методы
В Python существует огромное количество специальных методов, расширяющих возможности пользовательских классов. Например, можно определить вид объекта на печати, его «официальное» строковое представление или поведение при сравнениях. Узнать о них подробнее вы можете в официальной документации языка.
Принципы ООП на Python
Рассмотрим «большую тройку» объектно-ориентированной концепции: инкапсуляцию, полиморфизм и наследование.
Инкапсуляция
Все объекты в Python инкапсулируют внутри себя данные и методы работы с ними, предоставляя публичные интерфейсы для взаимодействия.
Атрибут может быть объявлен приватным (внутренним) с помощью нижнего подчеркивания перед именем, но настоящего скрытия на самом деле не происходит – все на уровне соглашений.
Если поставить перед именем атрибута два подчеркивания, к нему нельзя будет обратиться напрямую. Но все равно остается обходной путь:
Специальные свойства и методы класса, некоторые из которых вам уже знакомы, имеют двойные подчеркивания до и после имени.
Кроме прямого доступа к атрибутам ( obj.attrName ), могут быть использованы специальные методы доступа (геттеры, сеттеры и деструкторы):
Такой подход очень удобен, если получение или установка значения атрибута требует сложной логики.
__getattribute__ перехватывает все обращения (в том числе и к существующим атрибутам):
Таким образом, можно организовать динамический доступ к методам и свойствам объекта, как действуют, например, RPC-системы.
Наследование
Язык программирования Python реализует как стандартное одиночное наследование:
так и множественное:
Используя множественное наследования можно создавать классы-миксины (примеси), представляющие собой определенную особенность поведения. Такой микси можно «примешать» к любому классу.
Ассоциация
Кроме наследования, существует и другой способ организации межклассового взаимодействия – ассоциация (агрегация или композиция), при которой один класс является полем другого.
Ассоциированные объекты могут циклически ссылаться друг на друга, что ломает стандартный механизм сборки мусора. Избежать подобных проблем при ассоциации помогают слабые ссылки (модуль weakref ).
Полиморфизм
Концепция полиморфизма – важная часть ООП на Python. Все методы в языке изначально виртуальные. Это значит, что дочерние классы могут их переопределять и решать одну и ту же задачу разными путями, а конкретная реализация будет выбрана только во время исполнения программы. Такие классы называют полиморфными.
Впрочем, можно получить и доступ к методам класса-предка либо по прямому обращению, либо с помощью функции super :
Это возможно благодаря утиной типизации.
Множественная диспетчеризация
Виртуальные методы обеспечивают одиночную диспетчеризацию, при которой выбор конкретного метода зависит от объекта, в контексте которого произошел вызов. Мультиметоды позволяют выбирать нужную функциональность в зависимости от количества, типов или значений аргументов.
Программирование на Python не поддерживает мультиметоды из коробки, поэтому для их реализации необходимо подключать сторонние Python библиотеки, например, multimethods.py.
Подробнее о множественной диспетчеризации читайте в этой статье из серии «Очаровательный Python».
Порядок разрешения доступа к атрибутам
Каким же образом интерпретатор разрешает сложные запросы к свойствам и методам? Рассмотрим последовательность поиска на примере запроса obj.field :
Все эти проверки совершаются только для пользовательских атрибутов.
Метаклассы
Метаклассы – это классы, инстансы которых тоже являются классами.
Узнайте больше о метаклассах в Python из нашего материала.
ООП на Python
Подведем краткий итог всему вышесказанному и выделим основные особенности реализации ООП на Python:
Хотите лучше разобраться в объектно-ориентированном программировании? Смотрите понятный видеокурс по основам ООП.
🤹 Введение в объектно-ориентированное программирование (ООП) на Python
Leo Matyushkin
Объектно-ориентированное программирование – это метод структурирования программ путем объединения связанных свойств и методов в отдельные объекты. В этом руководстве мы познакомимся с основами объектно-ориентированного программирования на языке Python. Материал будет полезен абсолютным новичкам в ООП на Python. Чтобы проверить свои знания в Python, вы можете пройти наш тест на знание языка.
Текст публикации представляет собой незначительно сокращенный перевод статьи Дэвида Амоса Object-Oriented Programming (OOP) in Python 3.
Что собой представляет объектно-ориентированное программирование в Python?
Объектно-ориентированное программирование (ООП) – это парадигма программирования, которая предоставляет средства структурирования программ таким образом, чтобы их свойства и поведение были объединены в отдельные объекты.
Например, объект может представлять человека свойствами «имя», «возраст», «адрес» и методами (поведением) «ходьба», «разговор», «дыхание» и «бег». Или электронное письмо описывается свойствами «список получателей», «тема» и «текст», а также методами «добавление вложений» и «отправка».
Иными словами, объектно-ориентированное программирование – это подход для моделирования вещей, а также отношений между вещами. ООП моделирует сущности реального мира в виде программных объектов, с которыми связаны некоторые данные и которые могут выполнять определенные функции.
Другой распространенной парадигмой программирования является процедурное программирование, которое структурирует программу подобно рецепту. Такая программа предоставляет набор шагов в виде функций и блоков кода, которые последовательно выполняются для выполнения задачи.
Определим класс в Python
Примитивные структуры данных, такие как числа, строки и списки, предназначены для представления простых фрагментов информации: стоимость яблока, название стихотворения, список любимых цветов. Но бывает, что информация имеет более сложную структуру.
Допустим, вы хотите отслеживать работу сотрудников. Необходимо хранить основную информацию о каждом сотруднике: Ф.И.О., возраст, должность, год начала работы. Один из способов это сделать – представить каждого сотрудника в виде списка:
У этого подхода есть ряд проблем.
Во-первых, ухудшается читаемость кода. Чтобы понять, что kirk[0] ссылается на имя сотрудника, нужно перемотать код к объявлению списка.
Отличный способ сделать такой тип кода более удобным – использовать классы.
Классы и экземпляры
Итак, для создания пользовательских структур данных используются классы. Классы определяют функции, называемые методами класса. Методы описывают поведение – те действия, которые объект, созданный с помощью класса, может выполнять с данными.
Нужно понимать, что класс – это только план того, как что-то должно быть определено. Сам класс не содержит никаких данных. Класс Dog указывает, что для описания собаки необходимы кличка и возраст, но он не содержит ни клички, ни возраста какой-либо конкретной собаки.
Если класс является планом, то экземпляр – это объект, который построен по этому плану. Он содержит реальные данные, это настоящая собака. Например, 🐕 Майлз, которому недавно исполнилось четыре года.
Другая аналогия: класс – это бланк анкеты. Экземпляр – анкета, которую заполнили 📝. Подобно тому как люди заполняют одну и ту же форму своей уникальной информацией, так из одного класса может быть создано множество экземпляров. Обычно бланк анкеты сам по себе не нужен, он используется лишь для удобства оформления информации.
Как определить класс
В теле __init__() две инструкции, задействующие переменную self :
Атрибуты, созданные в __init__() называются атрибутами экземпляра. Значение атрибута экземпляра зависит от конкретного экземпляра класса. Все объекты Dog имеют имя и возраст, но значения атрибутов name и age будут различаться в зависимости от экземпляра Dog.
С другой стороны, можно создать атрибуты класса – атрибуты, которые имеют одинаковое значение для всех экземпляров класса. Вы можете определить атрибут класса, присвоив значение имени переменной вне __init__() :
Атрибуты класса определяются после имени класса. Им всегда должно быть присвоено начальное значение. Используйте атрибуты класса для определения свойств, которые должны иметь одинаковое значение для каждого экземпляра класса, а атрибуты экземпляров – для тех данных, которые отличают один экземпляр от другого.
Создание экземпляра класса в Python
Временно воспользуемся простейшим описанием класса, с которого мы начали:
Создание нового экземпляра класса похоже на вызов функции:
Важно, что следующий экземпляр Dog будет создан уже по другому адресу. Это совершенно новый экземпляр и он полностью уникален:
Хотя a и b являются экземплярами класса Dog, они представляют собой два разных объекта.
Атрибуты класса и экземпляра
Теперь возьмем последнюю рассмотренную нами структуру класса:
Для создания экземпляров объектов класса необходимо указать кличку и возраст собаки. Если мы этого не сделаем, то Python вызовет исключение TypeError :
Чтобы передать аргументы, помещаем значения в скобки после имени класса:
Но ведь в описании класса __init__() перечислены три параметра – почему в этом примере передаются только два аргумента?
После того как экземпляры созданы, записанные данные доступны в виде атрибутов экземпляра:
Значения атрибутов могут изменяться динамически:
Экземпляры не зависят друг от друга. Изменение атрибута класса у одного экземпляра не меняет его у остальных экземпляров:
Методы экземпляра
Мы добавили два метода экземпляра, возвращающих строковые значения. Метод description возвращает строку с описанием собаки, метод speak принимает аргумент sound :
В приведенном примере description() возвращает строку, содержащую информацию об экземпляре. При написании собственных классов такие методы, описывающие экземпляры, и правда полезны. Однако description() – не самый элегантный способ это сделать.
К примеру, когда вы создаете объект списка, вы можете использовать для отображения функцию print() :
Посмотрим, что произойдет, когда мы попробуем применить print() к объекту miles :
В большинстве практических приложений информация о расположении объекта в памяти не очень полезна. Поведение объекта при взаимодействии с функцией print() можно изменить, определив специальный метод __str__() :
Двойные символы подчеркивания в таких методах, как __init__() и __str__() указывают на то, что они имеют предопределенное поведение. Есть множество более сложных методов, которые вы можете использовать для настройки классов в Python, но это тема отдельной публикации.
Наследование от других классов в Python
Наследование – это процесс, при котором один класс принимает атрибуты и методы другого. Вновь созданные классы называются дочерними классами, а классы, от которых происходят дочерние классы, называются родительскими. Дочерние классы могут переопределять или расширять атрибуты и методы родительских классов.
Пример: место для выгула собак
Смоделируем несколько псов разных пород:
Создаём дочерние классы
Создадим дочерние классы для каждой из перечисленных пород. Так как порода теперь будет определяться дочерним классом, её нет смысла указывать в родительском классе:
Связь между родительским и дочерним классом определяется тем, что наследуемый класс ( Dog ) передается в качестве аргумента, принимаемого дочерним классом:
Дочерние классы действуют так же, как родительский класс:
Экземпляры дочерних классов наследуют все атрибуты и методы родительского класса:
Чтобы определить, к какому классу принадлежит определенный объект, используйте встроенную функцию type() :
Все объекты дочернего класса являются экземплярами родительского класса, но не других дочерних классов.
Теперь дадим нашим собакам немного полаять.
Расширяем функциональность родительского класса
Мы по-прежнему можем передать какой-то иной звук:
Изменения в родительском классе автоматически распространяются на дочерние классы. Если только изменяемый атрибут или метод не был переопределен в дочернем классе.
Иногда бывает необходимо учесть и поведение родительского класса, и дочернего, например, вызвать аналогичный метод родительского класса, но модифицировать его поведение. Для вызова методов родительского класса есть специальная функция super :
Заключение
Итак, в этом руководстве мы разобрали базовые понятия объектно-ориентированного программирования (ООП) в Python. Мы узнали:
Данный материал мы подготовили при поддержке компании GeekBrains — нашего партнёра, предоставляющего помощь в освоении Python. Если вы хотите получит навыки, необходимые для разработки на Python, не тратя лишнее время и силы на поиск знаний, инструментов и привыкание к разному стилю чтения курсов, обратите внимание на факультет Python-разработки. Программа и преподаватели имеют высокие оценки учащихся, а при успешном прохождении курса онлайн-университет гарантирует не только диплом, но и трудоустройство.
Объектно-ориентированное Программирование в Python
Объектно-ориентированное программирование (ООП) — это парадигма программирования, где различные компоненты компьютерной программы моделируются на основе реальных объектов. Объект — это что-либо, у чего есть какие-либо характеристики и то, что может выполнить какую-либо функцию.
Содержание
Представьте сценарий, где вам нужно разработать болид Формулы-1 используя подход объектно-ориентированного программирования. Первое, что вам нужно сделать — это определить реальные объекты в настоящей гонке Формула-1. Какие аспекты в Формуле-1 обладают определенными характеристиками и могут выполнять ту или иную функцию?
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Один из очевидных ответов на этот вопрос — гоночный болид. Условный болид может обладать такими характеристиками как:
Соответственно, болид можно запустить, остановить, ускорить, и так далее. Гонщик может быть еще одним объектом в Формуле-1. Гонщик имеет национальность, возраст, пол, и так далее, кроме этого, он обладает таким функционалом, как управление болидом, рулевое управление, переключение передач.
Как и в этом примере, в объектно-ориентированном программировании мы создадим объекты, которые будут соответствовать реальным аспектам.
Стоит обратить внимание на то, что объектно-ориентированное программирование — не зависящая от языка программирования концепция. Это общая концепция программирования и большинство современных языков, такие как Java, C#, C++ и Python поддерживают объектно-ориентированное программирование.
В этой статье мы разберем подробную инструкцию объектно-ориентированного программирования в Python, но перед этим, рассмотрим некоторые преимущества и недостатки объектно-ориентированного программирования.
Преимущества и недостатки ООП Python
Рассмотрим несколько основных преимуществ объектно-ориентированного программирования:
Хотя объектно-ориентированное программирование обладает рядом преимуществ, оно также содержит определенные недостатки, некоторые из них находятся в списке ниже:
В следующем разделе мы рассмотрим ряд самых важных концепций объектно-ориентированного программирования.
Как и следует из названия, объектно-ориентированное программирование — это речь об объектах. Однако, перед тем как создать объект, нам нужно определить его класс.
Класс
Класс в объектно-ориентированном программировании выступает в роли чертежа для объекта. Класс можно рассматривать как карту дома. Вы можете понять, как выглядит дом, просто взглянув на его карту.
Cам по себе класс не представляет ничего. К примеру, нельзя сказать что карта является домом, она только объясняет как настоящий дом должен выглядеть.
Отношение между классом и объектом можно представить более наглядно, взглянув на отношение между машиной и Audi. Да, Audi – это машина. Однако, нет такой вещи, как просто машина. Машина — это абстрактная концепция, которую также реализуют в Toyota, Honda, Ferrari, и других компаниях.
Давайте рассмотрим, как мы можем создать самый простой класс в Python. Взглянем на следующий код:
Объектно-ориентированное программирование Python (ООП в Python)
В этой статье мы расскажем об объектно-ориентированном программировании (ООП) в Python и его фундаментальных концепциях.
Введение в ООП в Python
Python — это мультипарадигмальный язык. Это означает, что он поддерживает различные подходы к программированию.
Одной из наиболее популярных парадигм является создание объектов. Она известна как объектно-ориентированное программирование (ООП).
Объект имеет две характеристики:
Рассмотрим на примере:
Объект – это попугай:
Концепция ООП в Python направлена на создание кода для многократного использования. Эта концепция также известна как DRY (Don’t Repeat Yourself).
В Python концепция ООП реализует несколько принципов:
| Наследование | Использование элементов из нового класса без изменения существующего класса. |
| Инкапсуляция | Скрытие приватных элементов класса от других объектов. |
| Полиморфизм | Концепция использования объекта с одинаковым интерфейсом без получения информации о его типе и внутренней структуре. |
Класс
Мы можем представить класс как эскиз попугая с метками. Он содержит все данные об имени, цвете, размере и т. д. На основе этого описания можно изучить попугая. В данном случае попугай является объектом.
Примером для класса попугая может быть:
Объект
Объект — это экземпляр класса. В определении класса задается только описание объекта. Пример создания объекта класса Parrot:
В данном случае obj является объектом класса Parrot.
Предположим, что у нас есть информация о попугае. Теперь нужно показать, как построить класс и объекты Parrot.
Пример 1. Создание класса и объекта в Python
Результат работы программы:
Сначала мы создаем класс с именем Parrot. Затем мы определяем атрибуты. Они являются характеристикой объекта.
Затем мы создаем экземпляры класса Parrot. В данном случае blu и woo являются ссылками на новые объекты.
После этого мы получаем доступ к атрибуту класса с помощью __class __.species. Атрибуты класса одинаковы для всех его экземпляров. Точно так же мы получаем доступ к атрибутам экземпляра, используя blu.name и blu.age. Но атрибуты экземпляра уникальны для каждого экземпляра класса.
Методы
Методы — это функции, определенные внутри класса. Они используются для определения поведения объекта.
Пример 2: Создание методов в Python
Результат работы программы:
В приведенном выше примере мы определяем два метода sing() и dance(). Их называют методами экземпляра, так как они вызываются для экземпляра объекта, то есть для blu.
Наследование
Наследование — это способ создания нового класса на основе старого. Новый класс является производным классом (дочерним). Существующий класс является базовым классом (родительским).
Пример 3: Использование наследования в Python
Результат работы программы:
Сначала мы создали два класса: Bird (родительский класс) и Penguin (дочерний класс). Он наследует функции родительского класса. Это прослеживается в методе swim().
Дочерний класс изменил поведение родительского класса – метод whoisThis(). Также мы расширяем родительский класс, создав новый метод run().
Мы используем функцию super() перед методом __init__(), чтобы извлечь содержимое метода __init__() из родительского класса в дочерний.
Инкапсуляция
Используя ООП в Python, мы можем ограничить доступ к методам и переменным. Это предотвращает изменение данных вне класса. Такой подход называется инкапсуляцией. В Python мы устанавливаем приватный модификатор доступа, используя в качестве префикса подчеркивание одинарное «_» или двойное «_ _» подчеркивание.
Пример 4: Инкапсуляция данных в Python
Когда мы запустим эту программу, результат будет следующим:
Мы попытались изменить цену, но не смогли, потому что Python рассматривает __maxprice, как приватные атрибуты. Чтобы изменить значение, мы использовали функцию сеттера. То есть, setMaxPrice(), которая принимает цену в качестве параметра.
Полиморфизм
Полиморфизм — это способность использовать в ООП общий интерфейс для нескольких форм (типов данных).
Предположим, что нужно раскрасить фигуру. Есть несколько вариантов фигуры (прямоугольник, квадрат, круг). Мы могли бы использовать тот же метод, чтобы закрасить любую форму. Эта концепция называется полиморфизмом.
Пример 5: Использование полиморфизма в Python
Чтобы реализовать полиморфизм, мы создали общий интерфейс. То есть, функцию flying_test(), которая может принимать любой объект. Затем мы передали объекты blu и peggy в функцию flying_test().
Преимущества использования ООП
Пожалуйста, опубликуйте свои комментарии по текущей теме статьи. Мы очень благодарим вас за ваши комментарии, лайки, дизлайки, отклики, подписки!
Пожалуйста, опубликуйте ваши комментарии по текущей теме материала. За комментарии, дизлайки, подписки, отклики, лайки низкий вам поклон!




