Классы и объекты в Python: руководство для начинающих
Разбираем ООП за готовкой печенья.
Классы и объекты — основа объектно-ориентированного программирования. С их помощью требования к программе превращаются в понятные структуры данных и правила взаимодействия между ними. Если вы пишете код и работаете над созданием ПО, то без объектов и классов вам не обойтись.
У нас уже есть статья про основные принципы ООП, а в этом материале мы детально и на примерах изучим работу с классами и объектами в Python.
Содержание
- Что такое классы и объекты в Python
- Как создать класс
- Как создать объект
- Как изменять объекты после создания
- Что такое деструктор и как его использовать
- Практические задачи
Что такое классы и объекты в Python
Класс — это шаблон, который описывает устройство и поведение объектов одного типа в коде.
Объект — это конкретный экземпляр класса. Его можно представить как контейнер, в котором хранятся данные (атрибуты) и описаны действия, которые можно выполнять с этими данными (методы).
Чтобы лучше понять эту концепцию, рассмотрим пример из реальной жизни. Кондитер использует одну формочку, чтобы испечь партию печенья. Все печенья имеют одинаковую форму, но могут отличаться начинкой и вкусом. В этом примере формочка — это класс, а отдельные печенья — объекты этого класса.
Классы и объекты помогают разработчикам создавать сложные структуры и экономить время. Вместо того чтобы каждый раз объявлять одни и те же переменные и функции, разработчик описывает их в классе и затем переиспользует, создавая объекты. При необходимости функциональность объектов легко расширить: достаточно дополнить существующий класс — и все объекты автоматически получат обновлённую логику.
Читайте также:
Как создать класс
Для создания классов в Python используется ключевое слово class. После него указывают имя класса с заглавной буквы и ставят двоеточие. Давайте создадим класс для печенья:
class Cookie:Теперь добавим в класс конструктор — специальный метод __init__. Он вызывается при создании объекта и используется для инициализации его атрибутов. У нашего печенья будет два атрибута: вкус и начинка.
def __init__(self, flavor, filling):
self.flavor = flavor # Атрибут экземпляра: вкус
self.filling = filling # Атрибут экземпляра: начинкаПараметр self — это ссылка на текущий объект класса. Через него мы сохраняем значения аргументов внутри конкретного экземпляра.
Теперь добавим метод класса — функцию show_info, которая будет выводить информацию о печенье:
def show_info(self):
return f"Печенье\nВкус: {self.flavor}\nНачинка: {self.filling}"Полностью код класса Cookie выглядит так:
class Cookie:
# Конструктор класса
def __init__(self, flavor, filling):
self.flavor = flavor # Атрибут экземпляра: вкус
self.filling = filling # Атрибут экземпляра: начинка
# Метод экземпляра
def show_info(self):
return f"Печенье\nВкус: {self.flavor}\nНачинка: {self.filling}"Теперь вся логика, связанная с печеньем, описана в одном месте — внутри класса.
Как создать объект
Чтобы создать объект, обратитесь к классу и передайте значения атрибутов в круглых скобках. В нашем примере используем класс Cookie и создадим два объекта: ванильное печенье с клубничной начинкой (vanilla_cookie) и шоколадное с марципаном (chocolate_cookie).
vanilla_cookie = Cookie("ваниль", "клубника")
chocolate_cookie = Cookie("шоколад", "марципан")Теперь вызовем метод show_info, чтобы проверить, как выглядят наши объекты:
print(vanilla_cookie.show_info())
print(chocolate_cookie.show_info())Если запустить код, то в терминале появится сообщение:
Печенье
Вкус: ваниль
Начинка: клубника
Печенье
Вкус: шоколад
Начинка: марципан
Кроме того, мы можем получить доступ к отдельным атрибутам объектов. Например, узнаем, какая начинка у печенек:
print(vanilla_cookie.flavor)
print(chocolate_cookie.filling)Получим ответ в терминале:
ваниль
марципан
Читайте также:
Как изменять объекты после создания
После создания объекта его атрибуты можно изменять. Например, превратить ванильное печенье в овсяное:
new_cookie = Cookie("ваниль", "клубника")
print(new_cookie.show_info())
new_cookie.flavor = "овсяное"
print(new_cookie.show_info())В этом примере мы напрямую присваиваем атрибуту новое значение. В результате сначала выводятся исходные характеристики объекта, а затем — обновлённые:
Печенье
Вкус: ваниль
Начинка: клубника
Печенье
Вкус: овсяное
Начинка: клубника
Прямое изменение атрибутов работает быстро и просто, но у такого подхода есть ограничения. Если логика изменения состояния объекта становится сложнее — например, требует проверки данных или дополнительных действий, — прямое присваивание перестаёт быть удобным.
Поэтому в объектно-ориентированном программировании часто используют методы класса, которые отвечают за изменение состояния объекта.
Добавим в класс Cookie метод для замены начинки:
def change_filling(self, new_filling):
self.filling = new_filling
return "Начинка обновлена."Теперь создадим объект шоколадного печенья и изменим его начинку с помощью метода change_filling:
chocolate_cookie = Cookie("шоколад", "марципан")
print(chocolate_cookie.show_info())
chocolate_cookie.change_filling("сливки") # Используем метод для замены начинки
print(chocolate_cookie.show_info())Такой подход удобнее масштабируется: если позже потребуется добавить проверку допустимых начинок или дополнительную логику, её можно реализовать внутри метода, не меняя код в местах использования объекта.
Полностью код обновлённого метода Cookie выглядит так:
class Cookie:
# Конструктор класса
def __init__(self, flavor, filling):
self.flavor = flavor # Атрибут экземпляра: вкус
self.filling = filling # Атрибут экземпляра: начинка
# Методы экземпляра
def show_info(self):
return f"Печенье\nВкус: {self.flavor}\nНачинка: {self.filling}\n"
def change_filling(self, new_filling):
self.filling = new_filling
return "Начинка обновлена."В Python можно добавлять новые атрибуты объекту даже после его создания — даже если они не описаны в классе. Например, можно создать объект печенья с атрибутами вкуса (flavor) и начинки (filling), а после добавить новый атрибут — тип посыпки (sprinkling):
chocolate_cookie = Cookie("шоколад", "марципан")
print(chocolate_cookie.show_info())
chocolate_cookie.sprinkling = "сахарная пудра"
print(chocolate_cookie.sprinkling)Интерпретатор выполнит этот код без ошибок. Однако такой подход может привести к путанице. Атрибут sprinkling появится только у этого объекта. У других экземпляров класса Cookie его не будет.
Что такое деструктор
В Python существует специальный метод __del__, который называют деструктором. Он может быть вызван, когда объект удаляется из памяти.
Добавим деструктор в класс Cookie:
class Cookie:
# Конструктор класса
def __init__(self, flavor, filling):
self.flavor = flavor # Атрибут экземпляра: вкус
self.filling = filling # Атрибут экземпляра: начинка
# Деструктор объекта
def __del__(self): # Используем метод деструктора со ссылкой на сам объект
print(f"Печенье удалено: вкус -- {self.flavor}, начинка -- {self.filling}") # Выводим сообщение о том, что объект удалён, указывая его атрибутыТеперь при завершении программы деструктор будет автоматически удалять объекты класса Cookie.
Важно понимать, что в Python вызов деструктора не гарантирован. Интерпретатор сам управляет памятью и может не вызвать __del__ в ожидаемый момент — или не вызвать вовсе, например при завершении программы.
Поэтому деструкторы редко используют в прикладном коде. Для управления ресурсами (файлами, соединениями, потоками) в Python применяют другие механизмы — например, контекстные менеджеры (with) и явное освобождение ресурсов.
Практика
Закрепим теорию, решив практические задачи. Постарайтесь выполнить их самостоятельно перед тем, как подглядывать в ответы.
Задача 1
Создайте класс Book с атрибутами названия (title), автора (author) и года печати (year). В качестве метода добавьте функцию info (), которая будет выводить атрибуты в формате «Название — Автор (Год)».
Решение
class Book:
def __init__(self, title, author, year):
self.title = title
self.author = author
self.year = year
def info(self):
return f"{self.title} -- {self.author} ({self.year})"
# Пример использования класса
new_book = Book("Мастер и Маргарита", "Михаил Булгаков", 1967)
print(new_book.info())Вот что должно получиться в терминале при запуске кода:
Мастер и Маргарита -- Михаил Булгаков (1967)Задача 2
Создайте класс Account для банковского счёта с атрибутами владельца (owner) и баланса (balance). Добавьте методы для пополнения счёта (deposit) и для снятия наличных (withdraw). Помните, что нельзя уводить баланс владельца в минус.
С помощью класса создайте объект и проведите с ним три операции пополнения и снятия. Порядок операций и сумму выберите сами. В конце выведите остаток на счету.
Решение
class Account:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = float(balance)
def deposit(self, amount):
amount = float(amount)
if amount <= 0:
return "Сумма пополнения должна быть больше 0."
self.balance += amount
return f"Пополнение: +{amount:.2f}. Баланс: {self.balance:.2f}"
def withdraw(self, amount):
amount = float(amount)
if amount <= 0:
return "Сумма снятия должна быть больше 0."
if amount > self.balance:
return f"Ошибка: недостаточно средств. Баланс: {self.balance:.2f}"
self.balance -= amount
return f"Снятие: -{amount:.2f}. Баланс: {self.balance:.2f}"
def info(self):
return f"Счёт: {self.owner}\nБаланс: {self.balance:.2f}"
# Операции со счётом
acc = Account("Василий", 100)
print(acc.deposit(50)) # 1) пополнение
print(acc.withdraw(30)) # 2) снятие
print(acc.withdraw(200)) # 3) попытка снять больше, чем есть на счету
print("\nИтог:")
print(acc.info())Вот что программа выведет в терминал:
Пополнение: +50.00. Баланс: 150.00
Снятие: -30.00. Баланс: 120.00
Ошибка: недостаточно средств. Баланс: 120.00
Итог:
Счёт: Tom
Баланс: 120.00Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!
Python для всех
Вы освоите Python на практике и создадите проекты для портфолио — телеграм-бот, веб-парсер и сайт с нуля. А ещё получите готовый план выхода на удалёнку и фриланс. Спикер — руководитель отдела разработки в «Сбере».
Пройти бесплатно