Классы
До этого программа хранила значения в отдельных переменных, а действия — в отдельных функциях. Для маленького скрипта этого достаточно. Но в проекте робота рядом появляются состояние левого мотора, правого мотора, режим движения, заряд, ошибки и методы управления. Класс помогает собрать данные и действия одного объекта в одну понятную модель.
Класс — описание будущих объектов. Объект — конкретный экземпляр класса во время работы программы. Данные объекта обычно называют атрибутами, а функции внутри класса — методами. Первый параметр метода по соглашению называется self и указывает на тот объект, с которым сейчас работает метод.
Зачем это нужно
Представим учебную модель мобильного робота. Без класса состояние можно хранить так:
left_speed = 0
right_speed = 0
mode = "stop"
Затем появляются функции stop_robot, move_forward, turn_left, и каждой нужно передавать или возвращать несколько связанных значений. Легко перепутать левую и правую скорость, забыть обновить режим или изменить одну часть состояния отдельно от другой.
Класс даёт имя целому объекту:
RobotState = скорости + режим + действия над ними
Это не делает программу автоматически правильной, но помогает держать связанные данные рядом с командами, которые их меняют.
Главная идея
Класс похож на чертёж, по которому можно создать объект:
class RobotState -> объект robot -> robot.stop(), robot.forward()
Минимальный пример:
class RobotState:
def __init__(self):
self.left_speed = 0
self.right_speed = 0
self.mode = "stop"
def stop(self):
self.left_speed = 0
self.right_speed = 0
self.mode = "stop"
robot = RobotState()
robot.stop()
print(robot.mode)
print(robot.left_speed, robot.right_speed)
Строка robot = RobotState() создаёт объект. Метод __init__ выполняется при создании и задаёт начальные значения. Запись self.left_speed означает атрибут текущего объекта, а не обычную локальную переменную функции.
Атрибуты объекта
Атрибут хранит состояние конкретного объекта. У двух объектов одного класса значения могут отличаться:
class Motor:
def __init__(self, name):
self.name = name
self.speed = 0
left_motor = Motor("left")
right_motor = Motor("right")
left_motor.speed = 30
right_motor.speed = 45
print(left_motor.name, left_motor.speed)
print(right_motor.name, right_motor.speed)
Здесь left_motor и right_motor созданы по одному описанию, но хранят разные скорости. Это удобно, когда в программе есть несколько похожих устройств.
Методы объекта
Метод — функция внутри класса. Он получает self, поэтому может читать и менять атрибуты объекта:
class Motor:
def __init__(self, name):
self.name = name
self.speed = 0
def set_speed(self, speed):
if speed < 0:
speed = 0
if speed > 100:
speed = 100
self.speed = speed
motor = Motor("left")
motor.set_speed(120)
print(motor.speed)
Вызов motor.set_speed(120) выглядит так, будто передан один аргумент. Python сам подставляет объект motor в параметр self. Поэтому в определении метода self есть, а при обычном вызове его не пишут.
Простая модель робота
Соберём состояние двух моторов в один объект:
class SimpleRobot:
def __init__(self):
self.left_speed = 0
self.right_speed = 0
self.mode = "stop"
def forward(self, speed):
self.left_speed = speed
self.right_speed = speed
self.mode = "forward"
def turn_left(self, speed):
self.left_speed = 0
self.right_speed = speed
self.mode = "left"
def stop(self):
self.left_speed = 0
self.right_speed = 0
self.mode = "stop"
robot = SimpleRobot()
robot.forward(40)
print(robot.mode, robot.left_speed, robot.right_speed)
robot.turn_left(30)
print(robot.mode, robot.left_speed, robot.right_speed)
robot.stop()
print(robot.mode, robot.left_speed, robot.right_speed)
Это всё ещё учебная модель. Она не отправляет сигнал на настоящие моторы, а только показывает, какие команды были бы выбраны. Такой объект можно проверить на обычном компьютере до подключения драйвера.
Когда класс пока не нужен
Класс полезен, когда есть объект с состоянием и несколькими действиями. Если нужна одна формула, обычная функция проще:
def centimeters_to_millimeters(distance_cm):
return distance_cm * 10
Не стоит создавать класс только ради красивого слова. Сначала спросите: «У этого объекта есть состояние, которое меняется между вызовами?» Если нет, функция обычно понятнее.
Что запомнить о классах
- Класс описывает, какие атрибуты и методы будут у объекта.
- Объект создаётся вызовом имени класса с круглыми скобками.
__init__задаёт начальное состояние объекта.selfуказывает на текущий объект внутри метода.- Атрибуты вида
self.nameпринадлежат объекту. - Метод может читать и менять состояние объекта.
- Для простой независимой формулы класс обычно не нужен.
Практика
Задание 1. Состояние мотора
Создайте класс Motor с атрибутами name и speed. Добавьте метод set_speed, который ограничивает скорость диапазоном от 0 до 100.
Задание 2. Два мотора
Создайте два объекта Motor: левый и правый. Задайте им разные скорости и выведите состояние каждого объекта.
Задание 3. Модель робота
Создайте класс SimpleRobot с методами forward, turn_left и stop. Проверьте, как меняются скорости и режим после каждого вызова.
Задание 4. Функция или класс
Для трёх задач решите, нужен ли класс: перевод сантиметров в миллиметры, состояние двух моторов, проверка расстояния по порогу. Объясните выбор.
Проверьте себя
- Чем класс отличается от объекта?
- Для чего нужен метод
__init__? - Почему внутри метода пишут
self.speed, а не простоspeed? - Почему
selfесть в определении метода, но не передаётся вручную при вызовеmotor.set_speed(50)? - В каком случае обычная функция проще класса?
Сначала ответьте без подсказки. Ответ можно считать полным, если вы:
- формулируете основную мысль своими словами;
- называете важные условия, ограничения или меры безопасности;
- для схемы, кода или расчёта показываете ход решения и ожидаемый результат.
Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.
Словарь статьи
- Класс — описание объектов с их атрибутами и методами.
- Объект — конкретный экземпляр класса во время выполнения программы.
- Атрибут — значение, связанное с объектом.
- Метод — функция, определённая внутри класса.
self— параметр метода, указывающий на текущий объект.__init__— специальный метод начальной настройки объекта.- Экземпляр — объект, созданный по классу.
Связанные темы
- Функции — методы классов строятся на той же идее вызываемого блока кода.
- Условия — проверки помогают методам выбирать допустимые значения.
- Работа с файлами — состояние объекта можно сохранять и загружать.
- Библиотеки и виртуальные окружения — многие библиотеки дают готовые классы для работы с устройствами.
Источники
- Python Tutorial. Classes: https://docs.python.org/3/tutorial/classes.html
- Python Language Reference. Class definitions: https://docs.python.org/3/reference/compound_stmts.html#class-definitions
- Python Language Reference. Special method names: https://docs.python.org/3/reference/datamodel.html#special-method-names