Объектно-ориентированное программирование в Python (ООП) #1

ООП для многих начинающих представляет определенные трудности в понимании этого вопроса. У меня также были самые общие понимания ООП. С учетом того, что при изучении python регулярно сталкиваюсь с понятием класса, я решил углубиться в эту тему и конечно же решил создать конспект из нескольких частей.

 

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

ООП

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

Понятия

Классы

Класс – это шаблон (чертеж), который определяет атрибуты (переменные) и методы (функции) объекта. Из одного класса можно создать сколько угодно объектов. Пример создания класса:

class MyClass:
    def __init__(self, x):
        self.my_variable = x
    def display_variable(self):
        print("Моя переменная:", self.my_variable)


MyClass(5).display_variable() # Моя переменная: 5

Объекты

Объект – это экземпляр класса. Он содержит данные, определенные в классе, и может вызывать методы класса. Инициализация класса – это процесс создания объекта класса и инициализации его атрибутов. В Python инициализация выполняется с помощью метода __init__, который является конструктором класса. В этом методе обычно устанавливаются начальные значения атрибутов объекта.

Когда вы создаете новый объект – экземпляр класса, метод __init__ автоматически вызывается для инициализации объекта.

В ООП объект является экземпляром класса. В Python практически все является объектами, в т.ч. числа, строки, списки и т.д.

Методы

 Методы – это функции, описанные внутри объекта или класса. Они могут изменять состояние объекта и выполнять операции с его данными. Объект вызывает методы с использованием точечной записи object.method().

Атрибуты

Атрибуты – это конкретные данные объекта. Это переменные, которые содержат значения, или методы, которые представляют функциональность объекта. Доступ к атрибутам происходит с использованием точечной записи (object.attribute).

Свойствам предпочтительней давать имена в виде существительных, а методам – в виде глаголов.

Принципы ООП

ООП базируется на трех основных принципах – инкапсуляция, полиморфизм, наследование.

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

Инкапсуляция в Python – это механизм, позволяющий скрыть атрибуты и методы класса от прямого доступа извне, чтобы обеспечить более безопасное и контролируемое взаимодействие с объектами класса. Инкапсуляция достигается путем использования особых конвенций и соглашений в именовании атрибутов и методов класса:

  • Префикс одного подчеркивания (_) перед именем атрибута или метода указывает, что он является “внутренним” и предназначен для использования только внутри класса.
  • Префикс двух подчеркиваний (__) перед именем атрибута или метода указывает, что он является “приватным” и недоступным для прямого доступа вне класса.

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

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

class ChildClass(BaseClass):
    # определение дочернего класса

В Python все встроенные и библиотечные классы, а также все созданные разработчиком программы классы прямо или косвенно наследуют единый базовый класс object.

Полиморфизм

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

Создаем свой класс

class Dom:
    """Класс с описанием характеристик дома"""
    color = "red"
    square = 100


print(Dom.__doc__)  # печатаем описание класса
print(Dom.color, Dom.square)  # печатаем атрибуты класса
dom2 = Dom()  # создаем экземпляр класса
dom3 = Dom()  # создаем экземпляр класса
print(type(dom2))  # является экземпляром класса Dom
print(isinstance(dom2, Dom))  # является экземпляром класса Dom
dom3.color = "black"  # создаем атрибут экземпляра класса
dom3.floors = 2  # создаем атрибут экземпляра класса
setattr(dom2, "windows", 6)  # создаем атрибут экземпляра класса
print(Dom.__dict__)  # Все атрибуты класса
print(dom2.__dict__)  # Все атрибуты экземпляра класса
print(dom3.__dict__)  # Все атрибуты экземпляра класса
d1 = dom3.floors  # получаем значение атрибута
print(d1)
d2 = getattr(dom2, "floors", "нет такого атрибута")  # получаем значение атрибута
print(d2)
delattr(dom3, "color")  # удаляем атрибут
print(dom3.__dict__)  # Все атрибуты экземпляра класса
print(dom3.color)  # получаем значение атрибута класса Dom
print(hasattr(dom3, "color"))  # проверяем наличие атрибута в экземпляре класса или в классе

__doc__ – это специальный атрибут в Python, который содержит строку документации для классов, функций, модулей и других объектов. Атрибут устанавливается во время определения объекта и не может быть изменен позже. Если документация не указана явно, значение атрибута __doc__ будет None.

__dict__ – это специальный атрибут в Python, который представляет собой словарь, содержащий атрибуты объекта. Словарь __dict__ не содержит атрибутов, определенных в родительских классах.

Функция isinstance() возвращает True, если объект является экземпляром любого указанного класса (классов) или его подкласса. Эту функцию часто используется для проверки типа объекта в условных операторах или для реализации полиморфного поведения.

Функция setattr() – это встроенная функция Python, которая устанавливает значение атрибута объекта. Эта функция полезна в ситуациях, когда имя атрибута хранится в переменной или генерируется динамически. 

Функция getattr() – это встроенная функция Python, которая получает значение атрибута объекта. Эта функция полезна в ситуациях, когда имя атрибута хранится в переменной или генерируется динамически. Если атрибута нет, то возвращается значение заданное в функции по умолчанию.

Функция delattr() -это встроенная функция Python, которая удаляет атрибут из объекта, если объект позволяет это. При удалении атрибута в родительском классе он не удаляется в дочерних классах.

Функция hasattr()  – это встроенная функция Python, которая проверяет, имеет ли объект заданный атрибут. Возвращает True, если атрибут существует, иначе False. Функция полезна для проверки наличия атрибута перед его использованием. Она также может использоваться для проверки наличия динамически сгенерированных атрибутов. При наличия атрибута в родительском классе  – возвращает True.

Создание объекта класса

В каждом классе языка Python есть магические методы, которые начинаются и заканчиваются двумя подчеркиваниями. Нас интересует __init__(self) –  инициализатор объекта класса.

Для создания объекта необходимо использовать метод __init__(). Этот метод инициализирует объект, устанавливая начальные значения его атрибутов. Его основная задача – инициализировать атрибуты экземпляра класса. Метод __init__() должен принимать хотя бы один параметр – self.

Конструктор класса – это специальный метод в объектно-ориентированном программировании, который вызывается при создании объекта. В Python конструктором класса является __init__. Этот метод вызывается при создании нового объекта класса.

self

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

Необходимо также упомянуть и про магический метод __del__ , который используется для удаления объектов из памяти и освобождения занятых ими ресурсов. Оператор del в Python используется для удаления объектов из памяти и освобождения занятых ими ресурсов. Создание метода __del__(self) не является обязательным в классах Python, но его можно определить для очистки любых ресурсов, занимаемых объектом, перед его удалением. Метод __del__ вызывается автоматически, когда счетчик ссылок на объект становится нулевым, что означает, что объект больше не используется и может быть удален из памяти.

Для понимания принципов работы создадим простую программу

class Dom:
    """Класс с описанием характеристик дома"""
    def __init__(self, width=6, length=6, color="red"):
        self.width = width
        self.length = length
        self.color = color

    def __del__(self):
        print(f"удаление экземпляра класса {self}")

    def set_description_dom(self, material):  # self ссылается на экземпляр класса из которого вызывается этот метод
        self.material = material  # благодаря self можно создать атрибут экземпляра класса
        description_dom = f"Дом имеет характеристики: ширина {self.width}, длина {self.length}. Дом из материала {self.material}."
        return description_dom

    def get_description_dom(self):
        return self.color



domik1 = Dom(7, 12, "blue")  # создаем экземпляр класса с заданными атрибутами
print(domik1.__dict__)  # выведем на печать все атрибуты экземпляра класса
domik2 = Dom()  # создаем экземпляр класса с атрибутами по умолчанию
print(domik2.__dict__)  # выведем на печать все атрибуты экземпляра класса


# выведем на печать описание дома с атрибутами - размеры дома + создаем атрибут материала - "кирпич")
print(domik2.set_description_dom("кирпич"))
# получаем и печатаем атрибут экземпляра класса - цвет дома
print(domik1.get_description_dom())  # печатаем атрибуты
print(domik1)  # строковое представление экземпляра класса Dom
print(domik2)  # строковое представление экземпляра класса Dom
domik1 = 777  # присваиваем новое значение. в этот момент удалится экземпляр класса
print(domik1)  # 777
# в конце программы будет удален и domik2 - экземпляр класса Dom

вот то, что получаем в терминале

если внимательно посмотрите на код и вывод в терминале, то все станет очевидным. Как работает __init__, __del__, self теперь должно быть понятным.

Стоит также знать, что существует метод __new__, который вызывается перед __init__ при создании нового экземпляра класса.

Значки в VSCODE

При написании кода в VScode после обращения к экземпляру класса с точкой появится выпадающий список, в котором по значку “куб” можно понять, что это название метода, а по значку “кирпич в квадратных скобках”, что это название атрибута.

Оцените статью
Репост в TG и VK
Алготрейдинг шаг за шагом. Создай торгового робота на Python с нуля по нашим урокам. Автоматизируй торговлю на бирже по собственной стратегии.