k09. классы, dataclasses и Enum
UAV Python Pro · Конспект K09 · Модуль M1. Python intensive: классы, dataclasses и Enum · Редакция 1.0 · После CHECKPOINT-K08
До сих пор телеметрию и точки маршрута вы часто описывали словарями и кортежами. Такой способ работает, но имена полей легко перепутать, а допустимые режимы полёта остаются «просто строками». На этом уроке вы научитесь собирать данные и поведение в типы: обычный класс с методами, dataclass для снимков состояния, Enum для ограниченного набора режимов и композицию объектов. Практика выполняется в виртуальном окружении. Полные тексты файлов k09_task*.py вложены в аккордеоны раздела практики.
Как устроены примеры. В теории каждый важный фрагмент кода дан дважды: сначала блок с подписью «Чистый код», затем раскрывающийся построчный разбор. В практике для каждой задачи в аккордеоне приведён полный исходный текст файла.
Главная мысль урока состоит в следующем. Класс описывает, какие данные хранит объект и какие действия с ними допустимы. Dataclass сокращает шаблонный код для структур данных вроде отсчёта телеметрии или точки маршрута. Enum фиксирует конечный набор допустимых значений, например режимов полёта, и снижает число ошибок из-за опечаток в строках. Композиция («объект содержит другие объекты») позволяет собирать статус аппарата из телеметрии, монитора батареи и других частей, не смешивая всё в одном гигантском словаре.
Содержание
- 1. Цели урока
- 2. Словарь урока
- 3. Зачем типы объектов в программах для БПЛА
- 4. Класс, экземпляр, __init__ и метод
- 5. Dataclass для снимков данных
- 6. Enum для режимов полёта
- 7. Композиция объектов
- 8. Точка маршрута и миссия
- 9. Типичные ошибки
- 10. Практика
- 11. Проверьте себя
- 12. Чек-лист самопроверки
- 13. Что дальше
1. Цели урока
После изучения этого урока вы будете уметь выполнять следующие действия.
- Вы будете объявлять класс с методом __init__ и обычными методами экземпляра.
- Вы будете объяснять разницу между классом и экземпляром (объектом).
- Вы будете создавать dataclass для снимка телеметрии и вызывать его методы.
- Вы будете описывать ограниченный набор режимов полёта через Enum и сравнивать элементы перечисления.
- Вы будете собирать составной объект по принципу композиции.
- Вы будете моделировать учебную точку маршрута и миссию списком точек.
- Вы будете понимать, когда словарь уже неудобен и когда тип с полями читается лучше.
2. Словарь урока
| Термин | Простыми словами |
|---|---|
| Класс | Описание типа объектов: какие поля они хранят и какие методы к ним применимы. |
| Экземпляр (объект) | Конкретная «вещь», созданная по классу, со своими значениями полей. |
| __init__ | Специальный метод, который вызывается при создании экземпляра. |
| self | Имя текущего экземпляра внутри методов класса. |
| Метод | Функция, объявленная внутри класса и работающая с экземпляром. |
| dataclass | Декоратор, который автоматически создаёт шаблонный код для класса данных. |
| Enum | Перечисление: фиксированный набор именованных допустимых значений. |
| Композиция | Способ сборки: объект содержит внутри себя другие объекты и использует их. |
| frozen dataclass | Dataclass, поля которого нельзя изменить после создания экземпляра. |
3. Зачем типы объектов в программах для БПЛА
Словарь удобен на первых шагах. Однако запись sample["altitud_m"] с опечаткой в ключе проявляется поздно, а строка режима "GUDED" не будет поймана до сравнения с эталоном. Класс и dataclass делают набор полей явным. Enum ограничивает множество допустимых режимов. Композиция позволяет не сваливать батарею, координаты и флаги связи в один плоский dict на сотню ключей.
Это не «академическое ООП ради ООП». Это способ уменьшить число скрытых ошибок в коде, который потом будет рядом с автопилотом.
↑ К оглавлению4. Класс, экземпляр, __init__ и метод
Класс — это описание типа объектов. Экземпляр, или объект, — конкретная сущность, созданная по этому описанию. Метод __init__ выполняется при создании экземпляра и обычно сохраняет начальные данные в полях. Имя self внутри методов обозначает текущий экземпляр.
Чистый код
# Пример: простой класс монитора напряжения
class BatteryMonitor:
"""Учебный монитор напряжения бортовой сети."""
def __init__(self, low_v: float = 14.4, critical_v: float = 14.0) -> None:
self.low_v = low_v
self.critical_v = critical_v
def classify(self, voltage_v: float) -> str:
if voltage_v >= self.low_v:
return "OK"
if voltage_v >= self.critical_v:
return "LOW"
return "CRITICAL"
monitor = BatteryMonitor()
print(monitor.classify(15.1))
print(monitor.classify(13.7))
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с последовательности символов «# →», содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
class BatteryMonitor: # → Объявляем класс — чертёж объектов одного типа. """Учебный монитор напряжения бортовой сети.""" # → Docstring класса: кратко, для чего этот тип нужен. def __init__(self, low_v: float = 14.4, critical_v: float = 14.0) -> None: # → __init__ вызывается при создании объекта. self — сам создаваемый экземпляр. self.low_v = low_v # → Сохраняем порог «низкое напряжение» в поле экземпляра. self.critical_v = critical_v # → Сохраняем порог «критическое напряжение». def classify(self, voltage_v: float) -> str: # → Метод экземпляра: работает с self и входным напряжением. if voltage_v >= self.low_v: # → Сравниваем с порогом, который хранится в объекте. return "OK" # → Напряжение не ниже порога low. if voltage_v >= self.critical_v: # → Иначе проверяем критический порог. return "LOW" # → Между critical и low. return "CRITICAL" # → Ниже критического порога. monitor = BatteryMonitor() # → Создаём объект (экземпляр) с порогами по умолчанию. print(monitor.classify(15.1)) # → Вызов метода у конкретного объекта. print(monitor.classify(13.7)) # → Другое напряжение — другая метка.Python
k09_task1_simple_class.py приведён в задаче 9.1.5. Dataclass для снимков данных
dataclass — это декоратор из стандартной библиотеки. Он создаёт для класса типичный код инициализации по аннотированным полям. Для снимка телеметрии или точки маршрута такой класс обычно читается лучше, чем словарь с строковыми ключами.
Чистый код
# Пример: dataclass снимка телеметрии
from dataclasses import dataclass
@dataclass
class TelemetrySample:
"""Один учебный отсчёт телеметрии."""
t_s: float
altitude_m: float
mode: str
voltage_v: float
def is_airborne(self, min_alt_m: float = 1.0) -> bool:
return self.altitude_m >= min_alt_m
s = TelemetrySample(1.0, 8.0, "GUIDED", 15.8)
print(s.mode, s.altitude_m, s.is_airborne())
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с последовательности символов «# →», содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
from dataclasses import dataclass # → Подключаем декоратор dataclass из стандартной библиотеки. @dataclass # → Декоратор сам создаёт __init__ и удобное представление объекта по аннотированным полям. class TelemetrySample: # → Имя типа для одного отсчёта телеметрии. """Один учебный отсчёт телеметрии.""" # → Краткое описание класса. t_s: float # → Поле: время в секундах. altitude_m: float # → Поле: высота в метрах. mode: str # → Поле: режим полёта строкой (ниже заменим на Enum). voltage_v: float # → Поле: напряжение в вольтах. def is_airborne(self, min_alt_m: float = 1.0) -> bool: # → Обычный метод можно добавлять в dataclass так же, как в обычный класс. return self.altitude_m >= min_alt_m # → Учебное правило «в воздухе» по высоте. s = TelemetrySample(1.0, 8.0, "GUIDED", 15.8) # → Создание экземпляра: аргументы соответствуют полям по порядку. print(s.mode, s.altitude_m, s.is_airborne()) # → Обращение к полям и вызов метода.Python
k09_task2_dataclass_telemetry.py приведён в задаче 9.2.6. Enum для режимов полёта
Enum (перечисление) задаёт конечный набор именованных допустимых значений. Вместо произвольной строки "GUIDED" вы работаете с элементом FlightMode.GUIDED. Опечатка в недопустимом режиме проявляется раньше, а сравнения становятся однозначнее.
Чистый код
# Пример: Enum режимов полёта
from enum import Enum
class FlightMode(Enum):
GUIDED = "GUIDED"
AUTO = "AUTO"
RTL = "RTL"
def needs_mission(mode: FlightMode) -> bool:
return mode is FlightMode.AUTO
mode = FlightMode("GUIDED")
print(mode, mode.value, needs_mission(mode))
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с последовательности символов «# →», содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
from enum import Enum # → Подключаем базовый класс перечислений. class FlightMode(Enum): # → Объявляем перечисление допустимых учебных режимов. GUIDED = "GUIDED" # → Элемент перечисления: имя GUIDED и значение-строка "GUIDED". AUTO = "AUTO" # → Элемент AUTO. RTL = "RTL" # → Элемент RTL (возврат к точке взлёта). def needs_mission(mode: FlightMode) -> bool: # → Функция принимает именно FlightMode, а не произвольную строку. return mode is FlightMode.AUTO # → Сравнение через is уместно для членов одного Enum. mode = FlightMode("GUIDED") # → Построение Enum из строки значения (как из телеметрии). print(mode, mode.value, needs_mission(mode)) # → mode — элемент Enum; value — строка; needs_mission — учебное правило.Python
k09_task3_enum_modes.py приведён в задаче 9.3.7. Композиция объектов
Композиция — это способ сборки системы, при котором один объект содержит внутри себя другие объекты и опирается на их методы. Формулировка «аппарат имеет телеметрию и монитор батареи» обычно точнее, чем попытка унаследовать «аппарат от батареи».
Чистый код
# Пример: композиция VehicleStatus
from dataclasses import dataclass
from enum import Enum
class FlightMode(Enum):
GUIDED = "GUIDED"
@dataclass
class TelemetrySample:
altitude_m: float
mode: FlightMode
voltage_v: float
class BatteryMonitor:
def __init__(self, low_v: float = 14.4) -> None:
self.low_v = low_v
def is_low(self, voltage_v: float) -> bool:
return voltage_v < self.low_v
class VehicleStatus:
def __init__(self, telemetry: TelemetrySample, battery: BatteryMonitor) -> None:
self.telemetry = telemetry
self.battery = battery
def summary(self) -> str:
batt = "LOW" if self.battery.is_low(self.telemetry.voltage_v) else "OK"
return f"mode={self.telemetry.mode.value} alt={self.telemetry.altitude_m} batt={batt}"
status = VehicleStatus(
TelemetrySample(15.0, FlightMode.GUIDED, 14.1),
BatteryMonitor(),
)
print(status.summary())
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с последовательности символов «# →», содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
class FlightMode(Enum): # → Режим полёта как Enum. GUIDED = "GUIDED" # → Учебный элемент перечисления. @dataclass # → Телеметрия — данные без сложной логики создания. class TelemetrySample: # → Снимок состояния. altitude_m: float # → Высота. mode: FlightMode # → Режим уже не «голая» строка, а Enum. voltage_v: float # → Напряжение. class BatteryMonitor: # → Отдельный объект с правилом оценки батареи. def __init__(self, low_v: float = 14.4) -> None: # → Порог задаётся при создании монитора. self.low_v = low_v # → Храним порог в экземпляре. def is_low(self, voltage_v: float) -> bool: # → Метод проверки. return voltage_v < self.low_v # → True, если напряжение ниже порога. class VehicleStatus: # → Сборка: статус аппарата «имеет» телеметрию и монитор. def __init__(self, telemetry: TelemetrySample, battery: BatteryMonitor) -> None: # → В конструктор передаём уже созданные части. self.telemetry = telemetry # → Сохраняем ссылку на телеметрию. self.battery = battery # → Сохраняем ссылку на монитор батареи. def summary(self) -> str: # → Метод сводки для печати. batt = "LOW" if self.battery.is_low(self.telemetry.voltage_v) else "OK" # → Композиция: status использует battery и telemetry вместе. return f"mode={self.telemetry.mode.value} alt={self.telemetry.altitude_m} batt={batt}" # → Собираем одну строку состояния. status = VehicleStatus( # → Создаём сборку. TelemetrySample(15.0, FlightMode.GUIDED, 14.1), # → Телеметрия как отдельный объект. BatteryMonitor(), # → Монитор с порогом по умолчанию. ) # → Конец создания VehicleStatus. print(status.summary()) # → Печатаем сводку.Python
k09_task4_composition.py приведён в задаче 9.4.8. Точка маршрута и миссия
frozen dataclass — это dataclass с параметром frozen=True. После создания экземпляра поля нельзя изменить. Для координат точки маршрута такая защита уменьшает риск случайной порчи данных в середине построения миссии.
Чистый код
# Пример: точка маршрута и миссия
from dataclasses import dataclass, field
@dataclass(frozen=True)
class Waypoint:
lat: float
lon: float
alt_m: float
name: str = ""
@dataclass
class Mission:
home: Waypoint
points: list[Waypoint] = field(default_factory=list)
def add(self, wp: Waypoint) -> None:
self.points.append(wp)
def count(self) -> int:
return len(self.points)
mission = Mission(home=Waypoint(55.75, 37.61, 0.0, "HOME"))
mission.add(Waypoint(55.76, 37.62, 40.0, "WP1"))
print(mission.count(), mission.points[0].name)
- Построчный разбор
Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с последовательности символов «# →», содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.
from dataclasses import dataclass, field # → field нужен для корректного значения списка по умолчанию. @dataclass(frozen=True) # → frozen=True: после создания менять поля точки нельзя — меньше случайных правок координат. class Waypoint: # → Учебная точка маршрута. lat: float # → Широта. lon: float # → Долгота. alt_m: float # → Высота в метрах. name: str = "" # → Необязательное имя точки. @dataclass # → Миссия изменяема: в неё добавляют точки. class Mission: # → Упорядоченный набор точек после home. home: Waypoint # → Точка «дом» хранится отдельно. points: list[Waypoint] = field(default_factory=list) # → default_factory=list — у каждой миссии свой новый список, а не один общий на всех. def add(self, wp: Waypoint) -> None: # → Добавление маршрутной точки. self.points.append(wp) # → Точка попадает в конец списка. def count(self) -> int: # → Сколько маршрутных точек (без home). return len(self.points) # → Длина списка points. mission = Mission(home=Waypoint(55.75, 37.61, 0.0, "HOME")) # → Создаём миссию с домашней точкой. mission.add(Waypoint(55.76, 37.62, 40.0, "WP1")) # → Добавляем первую маршрутную точку. print(mission.count(), mission.points[0].name) # → Печатаем число точек и имя первой.Python
k09_task5_waypoint_mission.py приведён в задаче 9.5.9. Типичные ошибки
| Ошибка | Что происходит | Как следует рассуждать |
|---|---|---|
| Забыли self в методе | Ошибка о числе аргументов | У методов экземпляра первый параметр — self |
| Список по умолчанию в поле dataclass как [] | Один список делится между экземплярами | Используйте field(default_factory=list) |
| Сравнивают Enum со строкой через == без .value | Сравнение даёт False | Сравнивайте с FlightMode.AUTO или используйте .value осознанно |
| Меняют поля frozen-объекта | FrozenInstanceError | Создайте новый экземпляр или снимите frozen, если изменение необходимо |
| Класс «на всё» с десятками ответственностей | Код трудно менять и тестировать | Делите по смыслу: телеметрия, батарея, миссия |
10. Практика
В каждой карточке задачи ниже в раскрывающемся блоке приведён полный текст соответствующего учебного файла. Этот текст совпадает с файлами в каталоге code/M01_python/. Рекомендуется такой порядок работы. Сначала внимательно прочитайте условие. Затем раскройте аккордеон, скопируйте код в файл проекта под тем же именем, запустите его в виртуальном окружении и сверьте вывод с ожидаемым результатом.
Задача 9.1. Простой класс
Файл практики: k09_task1_simple_class.py.
Создайте класс BatteryMonitor с порогами в __init__ и методом classify. Проверьте несколько напряжений, в том числе объект со своими порогами.
Ожидаемый результат. Для 15.1 ожидается OK, для 14.2 — LOW при порогах по умолчанию, для 13.7 — CRITICAL. Для strict-объекта 14.5 должно дать LOW.
- Полный текст файла k09_task1_simple_class.py
Скопируйте приведённое ниже содержимое в файл
code/M01_python/k09_task1_simple_class.pyв проекте PyCharm (виртуальное окружение) и запустите программу. Ниже приведён полный учебный текст файла с комментариями.# k09_task1_simple_class.py # Цель: простой класс с __init__ и методом. # Запуск: venv проекта. class BatteryMonitor: """Учебный монитор напряжения бортовой сети. Это не драйвер реального датчика. Класс только хранит пороги и отвечает, в каком учебном диапазоне находится напряжение. """ def __init__(self, low_v: float = 14.4, critical_v: float = 14.0) -> None: # Пороги задаём при создании объекта и храним в полях экземпляра self.low_v = low_v self.critical_v = critical_v def classify(self, voltage_v: float) -> str: """Вернуть учебную метку: OK, LOW или CRITICAL.""" if voltage_v >= self.low_v: return "OK" if voltage_v >= self.critical_v: return "LOW" return "CRITICAL" monitor = BatteryMonitor() print(monitor.classify(15.1)) print(monitor.classify(14.2)) print(monitor.classify(13.7)) strict = BatteryMonitor(low_v=14.8, critical_v=14.2) print("strict:", strict.classify(14.5))Python
Задача 9.2. Dataclass телеметрии
Файл практики: k09_task2_dataclass_telemetry.py.
Опишите TelemetrySample как dataclass, добавьте метод is_airborne и обойдите список образцов.
Ожидаемый результат. Три строки печати с метками ground или air в зависимости от высоты.
- Полный текст файла k09_task2_dataclass_telemetry.py
Скопируйте приведённое ниже содержимое в файл
code/M01_python/k09_task2_dataclass_telemetry.pyв проекте PyCharm (виртуальное окружение) и запустите программу. Ниже приведён полный учебный текст файла с комментариями.# k09_task2_dataclass_telemetry.py # Цель: dataclass для снимка телеметрии; method; список объектов. from dataclasses import dataclass @dataclass class TelemetrySample: """Один учебный отсчёт телеметрии в заданный момент времени.""" t_s: float altitude_m: float mode: str voltage_v: float def is_airborne(self, min_alt_m: float = 1.0) -> bool: """True, если высота не ниже учебного порога «в воздухе».""" return self.altitude_m >= min_alt_m samples = [ TelemetrySample(0.0, 0.3, "STABILIZE", 16.0), TelemetrySample(1.0, 8.0, "GUIDED", 15.8), TelemetrySample(2.0, 20.0, "AUTO", 15.6), ] for s in samples: flag = "air" if s.is_airborne() else "ground" print(f"t={s.t_s} alt={s.altitude_m} mode={s.mode} [{flag}]")Python
Задача 9.3. Enum режимов
Файл практики: k09_task3_enum_modes.py.
Объявите FlightMode, функции needs_mission и parse_mode. Обработайте строки GUIDED, AUTO и ACRO.
Ожидаемый результат. GUIDED и AUTO распознаются; для AUTO mission? True; ACRO даёт unknown mode.
- Полный текст файла k09_task3_enum_modes.py
Скопируйте приведённое ниже содержимое в файл
code/M01_python/k09_task3_enum_modes.pyв проекте PyCharm (виртуальное окружение) и запустите программу. Ниже приведён полный учебный текст файла с комментариями.# k09_task3_enum_modes.py # Цель: Enum для режимов полёта; безопасное сравнение. from enum import Enum class FlightMode(Enum): """Учебное перечисление режимов (не полный список ArduPilot).""" STABILIZE = "STABILIZE" LOITER = "LOITER" GUIDED = "GUIDED" AUTO = "AUTO" RTL = "RTL" LAND = "LAND" def needs_mission(mode: FlightMode) -> bool: """Нужен ли загруженный маршрут для этого режима (учебное правило).""" return mode is FlightMode.AUTO def parse_mode(raw: str) -> FlightMode | None: """Преобразовать строку телеметрии в Enum или вернуть None.""" try: return FlightMode(raw) except ValueError: return None for name in ("GUIDED", "AUTO", "ACRO"): mode = parse_mode(name) if mode is None: print(name, "-> unknown mode") else: print(name, "->", mode.name, "mission?", needs_mission(mode))Python
Задача 9.4. Композиция
Файл практики: k09_task4_composition.py.
Соберите VehicleStatus из TelemetrySample и BatteryMonitor и напечатайте summary.
Ожидаемый результат. Строка вида mode=GUIDED alt=15.0 batt=LOW при напряжении 14.1 и пороге 14.4.
- Полный текст файла k09_task4_composition.py
Скопируйте приведённое ниже содержимое в файл
code/M01_python/k09_task4_composition.pyв проекте PyCharm (виртуальное окружение) и запустите программу. Ниже приведён полный учебный текст файла с комментариями.# k09_task4_composition.py # Цель: композиция — объект «аппарат» содержит телеметрию и монитор батареи. from dataclasses import dataclass from enum import Enum class FlightMode(Enum): GUIDED = "GUIDED" AUTO = "AUTO" RTL = "RTL" @dataclass class TelemetrySample: altitude_m: float mode: FlightMode voltage_v: float class BatteryMonitor: def __init__(self, low_v: float = 14.4) -> None: self.low_v = low_v def is_low(self, voltage_v: float) -> bool: return voltage_v < self.low_v class VehicleStatus: """Учебная сборка: текущая телеметрия + проверка батареи.""" def __init__(self, telemetry: TelemetrySample, battery: BatteryMonitor) -> None: # Композиция: VehicleStatus «имеет» телеметрию и монитор self.telemetry = telemetry self.battery = battery def summary(self) -> str: low = self.battery.is_low(self.telemetry.voltage_v) batt = "LOW" if low else "OK" return ( f"mode={self.telemetry.mode.value} " f"alt={self.telemetry.altitude_m:.1f} " f"batt={batt}" ) tel = TelemetrySample(altitude_m=15.0, mode=FlightMode.GUIDED, voltage_v=14.1) status = VehicleStatus(tel, BatteryMonitor()) print(status.summary())Python
Задача 9.5. Точка маршрута и миссия
Файл практики: k09_task5_waypoint_mission.py.
Реализуйте frozen Waypoint и Mission с add, count и highest_alt_m.
Ожидаемый результат. points: 2; highest_alt_m: 50.0; печать WP1 и WP2.
- Полный текст файла k09_task5_waypoint_mission.py
Скопируйте приведённое ниже содержимое в файл
code/M01_python/k09_task5_waypoint_mission.pyв проекте PyCharm (виртуальное окружение) и запустите программу. Ниже приведён полный учебный текст файла с комментариями.# k09_task5_waypoint_mission.py # Цель: dataclass точки маршрута + класс миссии со списком точек. from dataclasses import dataclass, field @dataclass(frozen=True) class Waypoint: """Учебная точка маршрута. frozen=True — после создания поля не меняем.""" lat: float lon: float alt_m: float name: str = "" @dataclass class Mission: """Упорядоченный список точек (учебная миссия, не протокол MAVLink).""" home: Waypoint points: list[Waypoint] = field(default_factory=list) def add(self, wp: Waypoint) -> None: self.points.append(wp) def count(self) -> int: # home отдельно; points — маршрутные точки после home return len(self.points) def highest_alt_m(self) -> float: alts = [self.home.alt_m] + [p.alt_m for p in self.points] return max(alts) mission = Mission(home=Waypoint(55.751244, 37.618423, 0.0, "HOME")) mission.add(Waypoint(55.752000, 37.620000, 40.0, "WP1")) mission.add(Waypoint(55.753500, 37.615000, 50.0, "WP2")) print("points:", mission.count()) print("highest_alt_m:", mission.highest_alt_m()) for i, wp in enumerate(mission.points, start=1): print(f"{i}. {wp.name} alt={wp.alt_m}")Python
Задача 9.6. Сохранение в Git
Сохраните практику в истории Git.
git add code/M01_python/k09_*.py
git commit -m "K09: classes dataclasses enum composition mission"
11. Проверьте себя
- Чем класс отличается от экземпляра? Приведите пример из монитора батареи.
- Зачем в методах экземпляра нужен параметр self?
- Какую задачу решает декоратор @dataclass по сравнению с ручным __init__?
- Почему режим полёта удобнее хранить в Enum, а не только в str?
- Что такое композиция? Чем фраза «статус имеет телеметрию» отличается от наследования «статус является батареей»?
- Зачем для Waypoint указывают frozen=True?
- Почему default_factory=list используют для поля points, а не points=[] в определении класса?
- Почему учебный класс Mission ещё не является загрузкой миссии в автопилот по MAVLink?
12. Чек-лист самопроверки
- Я объясняю класс, экземпляр, __init__ и self законченными предложениями.
- Я создаю dataclass с полями и методом.
- Я объявляю Enum и преобразую строку в элемент перечисления.
- Я собираю объект по композиции из нескольких частей.
- Я моделирую Waypoint и Mission и понимаю ограничение frozen.
- Я открывал аккордеоны практики и сверял полный код с запуском в виртуальном окружении.
- Я запускал k09_task1 … k09_task5 в venv.
- Я сделал git commit по K09.
K09 чек-лист закрыт. Далее следует урок K10 о потоках, asyncio и очереди сообщений — то есть о том, как совмещать приём телеметрии и отправку команд.13. Что дальше
- Предыдущий урок: K08 · Исключения, журналирование и отладка
- Текущий урок: K09 · Классы, dataclasses и Enum
- Следующий урок: K10 · Потоки, asyncio, очередь сообщений
- Горизонт модуля M1: K12 и контрольная точка G1
docs/05_EDITOR_STYLE_GUIDE.md.