Гид по технологиям

Основы классов в Python

5 min read Программирование Обновлено 06 Apr 2026
Основы классов в Python
Основы классов в Python

Спортивный автомобиль на дороге — иллюстрация класса Car

Что такое класс (кратко)

Класс — это расширяемый фрагмент кода, описывающий структуру и поведение объектов одного типа. Объект класса — это конкретный экземпляр с собственным состоянием.

Ключевые варианты поиска и намерения: классы Python, self в Python, инкапсуляция, методы доступа, dataclass.

Основные понятия

  • Шаблон: класс описывает поля (атрибуты) и методы (поведение).
  • Экземпляр: объект, созданный по шаблону класса.
  • Атрибуты: переменные состояния экземпляра.
  • Методы: функции, связанные с экземпляром.

Коротко: self — ссылка на текущий экземпляр (автоматически передаётся при обращении к методу). Конструктор (init) инициализирует состояние.

Пример класса (Car)

Ниже — исходный пример класса, как он был в оригинальном материале. Он демонстрирует базовую структуру, но содержит ряд недостатков (о которых мы расскажем дальше).

  
class Car:  
#Constructor  
#the init method is responsible for initialising the values of the instance #variables in the class.  
def __init__(self, car_name, driver_name, license_plate_number,   
current_speed, speeding_charge, colour):  
self.car_name = car_name  
self._driver_name = driver_name  
self._license_plate_number = license_plate_number  
self._current_speed = current_speed  
self._speeding_charge = speeding_charge  
self._colour = colour  
#Accessor methods  
#The get_car_name method returns the name of the car  
def get_car_name(self):  
return self._car_name  
  
#The get_driver_name method returns the name of the driver  
def get_driver_name(self):  
return self._driver_name  
  
#The get_license_plate method returns the license plate of the car  
def get_license_plate(self):  
return self._license_plate  
  
#The get_current_speed method returns the current speed at which the car is #moving  
def get_current_speed(self):  
return self._current_speed  
  
#The get_speeding_charge method returns the total amount of money that the   
#driver has to pay for over-speeding  
def get_speeding_charge(self):  
return self._speeding_charge  
  
#The get_colour method returns the colour of our sweet ride!  
def get_colour(self):  
return self._colour  
  
#Mutator methods  
#The set_driver value changes the driver of our car.  
def set_driver(self, new_driver):  
self._driver_name = new_driver  
  
#The speeding_ticket method ensures that the driver is charged 50 bucks when#he or she caught speeding above 140 miles per hour :(  
def speeding_ticket(self, current_speed):  
if current_speed <= 140:  
return False  
else:  
self._speeding_charge += 50  
return True  
  
#The make_payment method ensures that the driver is able to pay for all the #amount that he or she owes for speeding ticket charges.  
def make_payment(self, amount_paid):  
self._speeding_charge -= amount_paid  

Комментарии к примеру

  • Этот класс моделирует автомобиль с состоянием: имя автомобиля, имя водителя, номер, текущая скорость, штрафы, цвет.
  • Логика штрафа: если скорость превышает 140 миль/ч, к счёту добавляется $50. 140 миль/ч ≈ 225 км/ч.
  • В коде есть опечатки и отсутствие проверок типов и диапазонов (это потенциальный источник ошибок).

Разбор ключевых частей

Self

self — это ссылка на конкретный экземпляр. При вызове instance.get_colour() интерпретатор автоматически передаёт объект как первый аргумент, поэтому программист не указывает self вручную.

Конструктор

init создаёт и инициализирует состояние нового объекта. Пример использования:

# создание экземпляра
Car("Bugatti", "David Sasu", 90828, 0, 0, "Cherry Red")

В нашем примере объект состоит из атрибутов: _car_name, _driver_name, _license_plate, _current_speed, _speeding_charge, _colour.

Аксессоры (Accessor methods)

Аксессоры возвращают состояние экземпляра (get_car_name, get_driver_name, get_license_plate, get_current_speed, get_speeding_charge, get_colour).

Мутаторы (Mutator methods)

Мутаторы изменяют состояние (set_driver, speeding_ticket, make_payment).

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

Инкапсуляция — принцип ООП, предполагающий скрытие внутренней реализации и предоставление ограниченного интерфейса. В Python принято использовать соглашение с одним подчёркиванием _attr для обозначения защищённых атрибутов.

Почему исходная реализация ненадёжна

  • Нет проверки типов аргументов (строка вместо числа может вызвать исключение).
  • Ошибки имён: в getcarname возвращается self._car_name, тогда как в __init задано self.car_name — логическая ошибка.
  • Нет ограничений на значения (скорость может быть отрицательной, плата — отрицательной и т. д.).
  • Метод speeding_ticket принимает current_speed, но класс уже хранит _current_speed — дублирование информации.

Важно: 140 миль/ч — очень большой порог; если ваша бизнес-логика использует другие единицы, явно документируйте это и приводите значения в международных единицах.

Важно: всегда валидируйте входные данные и придерживайтесь единообразия имён атрибутов.

Улучшенная версия класса — шаблон и паттерны

Ниже — улучшенный пример на Python 3 с аннотациями типов, свойствами и валидацией. Этот код демонстрирует лучшие практики: единый источник правды для скорости, проверку типов и использование свойств для доступа.

from typing import Union

class Car:
    """Простой и безопасный класс автомобиля."""

    SPEED_LIMIT_MPH = 140  # порог для штрафа в милях в час
    SPEEDING_FINE_USD = 50  # сумма штрафа в долларах

    def __init__(self, car_name: str, driver_name: str, license_plate_number: Union[str,int],
                 current_speed: float = 0.0, speeding_charge: float = 0.0, colour: str = "") -> None:
        if not isinstance(car_name, str):
            raise TypeError("car_name must be a string")
        if not isinstance(driver_name, str):
            raise TypeError("driver_name must be a string")
        if not isinstance(current_speed, (int, float)):
            raise TypeError("current_speed must be a number")
        if current_speed < 0:
            raise ValueError("current_speed cannot be negative")
        if speeding_charge < 0:
            raise ValueError("speeding_charge cannot be negative")

        self._car_name = car_name
        self._driver_name = driver_name
        self._license_plate = str(license_plate_number)
        self._current_speed = float(current_speed)
        self._speeding_charge = float(speeding_charge)
        self._colour = colour

    # свойства (безопасный доступ)
    @property
    def car_name(self) -> str:
        return self._car_name

    @property
    def driver_name(self) -> str:
        return self._driver_name

    @driver_name.setter
    def driver_name(self, new_driver: str) -> None:
        if not isinstance(new_driver, str):
            raise TypeError("driver_name must be a string")
        self._driver_name = new_driver

    @property
    def current_speed(self) -> float:
        return self._current_speed

    @current_speed.setter
    def current_speed(self, speed: float) -> None:
        if not isinstance(speed, (int, float)):
            raise TypeError("speed must be a number")
        if speed < 0:
            raise ValueError("speed cannot be negative")
        self._current_speed = float(speed)

    @property
    def speeding_charge(self) -> float:
        return self._speeding_charge

    def apply_speeding_ticket(self) -> bool:
        """Применяет штраф, если текущая скорость больше порога. Возвращает True, если добавили штраф."""
        if self._current_speed > self.SPEED_LIMIT_MPH:
            self._speeding_charge += self.SPEEDING_FINE_USD
            return True
        return False

    def make_payment(self, amount_paid: float) -> None:
        if not isinstance(amount_paid, (int, float)):
            raise TypeError("amount_paid must be a number")
        if amount_paid < 0:
            raise ValueError("amount_paid cannot be negative")
        self._speeding_charge = max(0.0, self._speeding_charge - float(amount_paid))

    def __str__(self) -> str:
        return f"{self._car_name} ({self._license_plate}) — водитель: {self._driver_name}, скорость: {self._current_speed} миль/ч"

Пояснения:

  • Использованы свойства (property) вместо явных get/set методов — это более «питоничный» стиль.
  • Аннотации типов помогают инструментам статической проверки и IDE.
  • Валидация предотвращает неожиданное поведение.

Альтернативные подходы

  • Dataclasses: когда нужен простой контейнер данных, используйте @dataclass для автоматической генерации init, repr и сравнения.
  • namedtuple / typing.NamedTuple: для неизменяемых структур данных.
  • Функциональный подход: если нет необходимости в состоянии, используйте чистые функции и структуры данных.

Пример dataclass для простых случаев:

from dataclasses import dataclass

@dataclass
class SimpleCar:
    car_name: str
    driver_name: str
    license_plate: str
    current_speed: float = 0.0
    speeding_charge: float = 0.0
    colour: str = ""

Когда классы — плохой выбор

  • Если вам нужно только хранить набор полей без поведения — проще использовать dataclass или словарь.
  • Маленькие утилиты и одноразовые преобразования проще сделать функциями.
  • Чрезмерное применение ООП может усложнять код (анти-паттерн: «анемичная модель» — класс только с геттерами/сеттерами и логикой вне класса).

Ментальные модели и эвристики

  • Класс = чертёж; экземпляр = дом, построенный по чертежу.
  • «Единый источник правды»: не дублируйте данные в объекте (например, current_speed и current_speed в аргументах методов).
  • Правило YAGNI: не добавляйте сложные механизмы, пока они реально не нужны.

Критерии приёмки

  1. Конструктор создаёт объект с указанными атрибутами и корректными типами.
  2. Установка current_speed < 0 вызывает ValueError.
  3. apply_speeding_ticket добавляет штраф только если скорость > 140 миль/ч.
  4. make_payment снижает speeding_charge и никогда не делает её отрицательной.
  5. Строковое представление (str) содержит имя автомобиля и номер.

Мини‑методология при разработке класса

  1. Определите состояние (список полей).
  2. Опишите требуемое поведение (методы).
  3. Выберите представление (dataclass vs класс с логикой).
  4. Напишите тесты для граничных случаев.
  5. Добавьте валидацию и документацию.

Тесты и случаи приёмки (примеры)

  • Создать Car(“A”, “B”, “123”, 0, 0, “red”) — ожидается успешное создание.
  • Установить current_speed = -10 — ожидается ValueError.
  • Для скорости 141 вызвать apply_speeding_ticket — speeding_charge увеличится на 50.
  • Оплатить сумму больше текущей — speeding_charge станет 0.

Чек‑лист по ролям

  • Новичок:
    • Могу создать экземпляр класса.
    • Понимаю, что такое self и init.
  • Ревьювер кода:
    • Проверить валидацию типов и диапазонов.
    • Убедиться, что нет дублирования состояния.
  • Поддерживающий инженер:
    • Добавить тесты для пограничных случаев.
    • Документировать единицы измерения и валюту.

Краткий словарь (1‑строчник)

  • Класс: шаблон для объектов.
  • Экземпляр: объект, созданный по классу.
  • self: ссылка на текущий экземпляр.
  • Конструктор (init): инициализирует новый объект.
  • Аксессор/геттер: возвращает значение атрибута.
  • Мутатор/сеттер: изменяет значение атрибута.
  • Инкапсуляция: скрытие внутренней реализации.

Факт‑бокс

  • Порог штрафа в примере: 140 миль/ч ≈ 225 км/ч.
  • Штраф в примере: $50 (USD).
  • Рекомендуемая практика: использовать аннотации типов и свойства для публичного API класса.

Заключение

Вы изучили основные концепции классов в Python: что такое self, как работает конструктор, чем отличаются аксессоры и мутаторы, и почему важна инкапсуляция и валидация. Практикуйтесь с небольшими примерами, затем переводите успешные шаблоны в более сложные системы.

Краткое резюме:

  • Класс — это шаблон для создания объектов.
  • В Python предпочтительнее свойства и аннотации типов.
  • Всегда валидируйте входные данные и пишите тесты.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро