Перейти к содержимому
k05

k05. Управление потоком и функции

k05. Управление потоком и функции

UAV Python Pro · Конспект K05 · Модуль M1. Python intensive: управление потоком и функции · Редакция 1.2 · После CHECKPOINT-K04

На занятии K03 вы уже знакомились с простыми условными ветвлениями, которые записываются с помощью ключевого слова if. На занятии K04 вы научились хранить связанные значения в структурах list и dict. Теперь нам необходимо научиться, во-первых, выполнять одно и то же действие многократно, то есть пользоваться циклами, и, во-вторых, выносить повторяющуюся логику в отдельные именованные блоки кода, которые называются функциями. Каждая функция имеет собственный вход, то есть набор принимаемых данных, и собственный выход, то есть возвращаемый результат. Без этих средств программы для обработки телеметрии и для проверок безопасности постепенно превращаются в длинный, монолитный код, который трудно читать и трудно изменять. Практические задания выполняются в виртуальном окружении проекта K01; соответствующие файлы расположены в каталоге code/M01_python/k05_*.py.

Главная мысль этого занятия состоит из двух положений. Первое положение относится к циклам. Цикл необходим тогда, когда одно и то же действие требуется выполнить многократно; такое повторение производится либо для каждого элемента какой-либо коллекции, либо до тех пор, пока некоторое условие остаётся истинным. Второе положение относится к функциям. Функция необходима тогда, когда повторяющемуся действию требуется дать собственное имя, передать в него входные данные и получить от него результат. Для инженера, который работает с БПЛА, полезно выработать устойчивую привычку: разделять чистый расчёт и побочный эффект. Чистым расчётом мы называем функцию, которая только вычисляет и возвращает ответ. Побочным эффектом мы называем то, что функция делает сверх возвращаемого значения, например печатает текст на экран; позднее такая функция может отправлять команду по протоколу MAVLink. Допустимо объединять расчёт и побочный эффект в одной функции, однако отладка подобного кода потребует больше усилий.

Рабочие файлы: code/M01_python/k05_task1_while_countdown.py и соседние файлы, имена которых начинаются с префикса k05_ и заканчиваются расширением .py.

Содержание

1. Цели урока

По завершении этого занятия вы будете обладать следующими умениями.

  • Вы сможете объяснить различие между циклом for и циклом while и выбрать из них тот, который соответствует поставленной задаче.
  • Вы научитесь осознанно применять операторы break и continue.
  • Вы научитесь объявлять функцию с помощью ключевого слова def, передавать в неё аргументы и возвращать результат с помощью оператора return.
  • Вы научитесь писать краткий docstring, то есть описание функции, сформулированное своими словами.
  • Вы научитесь задавать аргументам значения по умолчанию и вызывать функцию с указанием имён аргументов.
  • Вы научитесь читать и записывать простые подсказки типов вида (x: float) -> str.
  • Вы научитесь отличать чистую функцию, которая только вычисляет результат, от функции с побочным эффектом, которая, например, печатает текст, а позднее сможет отправлять команду.
  • Вы научитесь собирать несколько небольших функций для работы со структурой list[dict], в которой хранится телеметрия из занятия K04.
Значение этого материала для работы с БПЛА: такие проверки, как «высота находится в допустимых пределах?», «напряжение не является критическим?», «режим AUTO присутствует в пакете данных?», будут выполняться многократно. Функция предоставляет имя для каждого подобного действия. Цикл предоставляет способ последовательно перебрать все точки миссии или все записи лога.
↑ К оглавлению

2. Словарь урока

ТерминОбъяснение простыми словами
Цикл Конструкция языка, которая многократно повторяет выполнение некоторого блока кода.
for Цикл вида «для каждого элемента коллекции», например для каждого элемента списка или строки.
while Цикл вида «пока условие остаётся истинным». Ответственность за то, чтобы условие в определённый момент стало ложным, лежит на программисте.
Итерация Одно однократное выполнение тела цикла.
break Оператор, который немедленно завершает выполнение текущего цикла.
continue Оператор, который пропускает оставшуюся часть тела цикла и переходит к следующей итерации.
Функция Именованный блок кода, который можно вызывать многократно, передавая ему различные данные.
def Ключевое слово Python, которое означает «объявляю функцию».
Параметр Имя входа функции, которое указывается в заголовке, записанном после ключевого слова def. Например, в объявлении def f(voltage_v): слово voltage_v является параметром.
Аргумент Конкретное значение, которое передаётся в функцию при её вызове. В вызове f(15.0) число 15.0 является аргументом.
return Оператор, который возвращает результат из функции в ту точку программы, откуда эта функция была вызвана, и завершает выполнение функции.
None Специальное значение «ничего». Если оператор return в функции отсутствует, функция всё равно возвращает значение None.
docstring Строка документации, которая располагается сразу под строкой def и заключается в тройные кавычки. Она описывает, что именно делает функция.
Type hint Подсказка о типах данных, которая указывается в заголовке функции. На начальном этапе обучения Python не проверяет такие подсказки строго, однако они облегчают чтение кода.
Побочный эффект (side effect) Действие, которое функция выполняет сверх возврата значения: печать текста, запись в файл, отправка команды, изменение глобальных данных.
Чистая функция Функция, которая ведёт себя как математическая формула: её результат зависит только от входных данных, она не изменяет окружение и, в частности, не печатает текст и не отправляет команды.
↑ К оглавлению

3. Циклы for и while

Сначала мы рассмотрим два вида циклов по отдельности. В конце этого раздела мы поместим отдельный блок, который объясняет, как выбрать между циклами for и while; в этом блоке будут приведены примеры из повседневной жизни и из области беспилотной авиации, а также будет дано полное, а не сокращённое объяснение.

for — напоминание о том, что было на занятии K 04

Цикл for следует читать следующим образом: «для каждого элемента, который содержится в данной коллекции, выполни тело цикла».

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

# Имеется готовый список из трёх режимов
modes = ["GUIDED", "AUTO", "RTL"]

# На каждом шаге переменная mode содержит очередную строку из списка
for mode in modes:
    print("mode:", mode)
Когда цикл for является естественным первым выбором: когда у вас уже имеется коллекция и требуется обработать каждый её элемент либо почти каждый элемент. При обработке логов и миссий это наиболее частый случай применения циклов.

while — повторение, пока условие остаётся истинным

Цикл while устроен иным образом. У него нет списка элементов; вместо списка у него есть условие. Интерпретатор Python многократно выполняет тело цикла до тех пор, пока это условие остаётся истинным, то есть пока оно принимает значение True.

На программиста возлагается важная обязанность: внутри тела цикла while должно происходить изменение, которое влияет на условие, чтобы в некоторый момент условие стало ложным. Если такое изменение отсутствует, цикл не завершится никогда; подобное состояние называется бесконечным циклом.

# Учебный пример: «выполни три шага ожидания, затем выведи ready»
# Этот пример не является ожиданием реального heartbeat MAVLink,
# он лишь демонстрирует форму цикла while

steps_left = 3  # переменная хранит, сколько шагов ещё осталось

print("start wait loop")
while steps_left > 0:
    # Пока steps_left больше нуля, печатаем сообщение и уменьшаем счётчик
    print(f"waiting... steps_left={steps_left}")
    steps_left = steps_left - 1  # без этой строки условие всегда остаётся True

print("ready")

Разберём этот пример по шагам.

  1. В начальный момент переменная steps_left равна трём. Условие «три больше нуля» истинно, поэтому выполнение входит в цикл.
  2. Тело цикла печатает сообщение и уменьшает значение переменной steps_left до двух.
  3. Условие проверяется снова и снова оказывается истинным; так продолжается до тех пор, пока переменная не достигнет нуля.
  4. Когда переменная steps_left становится равной нулю, условие оказывается ложным; цикл завершается, и печатается сообщение ready.
Бесконечный цикл. Если программист забудет изменить переменную, которая участвует в условии, программа перестанет отвечать. В среде PyCharm выполнение программы в этом случае следует остановить с помощью красной кнопки Stop. В коде, который работает на борту аппарата, бесконечные циклы без паузы и без условия выхода по какому-либо событию представляют собой отдельную опасность. Пока мы тренируемся только на коротких учебных циклах while.

Как выбрать между циклами for и while

Ниже приводится не краткая формула, а полный порядок рассуждения, который позволяет принять правильное решение.

Шаг первый. Сформулируйте вопрос: «Имеется ли у меня список или иная коллекция, по которой необходимо пройти?»

  • Если ответ положительный, то почти всегда следует выбрать цикл for.
  • Примерами таких коллекций служат все точки миссии, все строки лога режимов и все записи телеметрии в переменной samples.

Шаг второй. Если готовой коллекции нет, сформулируйте следующий вопрос: «Требуется ли повторять действие до наступления некоторого события или до тех пор, пока счётчик не достигнет нуля?»

  • Если ответ положительный, то следует рассмотреть цикл while.
  • Учебными примерами служат следующие задачи: уменьшать переменную steps_left, пока она не станет равной нулю; повторять попытку, пока флаг ready не примет значение True. В обоих случаях флаг или счётчик программист устанавливает самостоятельно в коде.

Шаг третий. Приведите формальное обоснование выбора.

  • Цикл for применяется тогда, когда заранее известен набор элементов и требуется обработать каждый из них в этом наборе.
  • Цикл while применяется тогда, когда заранее неизвестно количество повторений и продолжение работы определяется исключительно значением условия.
  • В обоих случаях условие или перебор элементов должны быть записаны в коде явно и корректно. Интерпретатор не может принимать интуитивных решений; он руководствуется только значениями переменных и результатами проверок, которые вы записали.

Шаг четвёртый. Подготовка к будущему материалу (можно прочитать, не выполняя).

Когда мы перейдём к библиотеке pymavlink, нам часто будет требоваться следующая конструкция: повторять чтение сообщений до тех пор, пока не будет получено сообщение нужного типа либо пока не истечёт отведённое время. По своей форме такая конструкция ближе к циклу while или к циклу, который завершается оператором break по истечении таймаута. Сейчас писать код для pymavlink не требуется. Достаточно запомнить общее правило: цикл while соответствует формулировке «пока не выполнено условие», а цикл for соответствует формулировке «для каждого элемента уже имеющегося набора».

Краткое резюме после полного объяснения: если имеется коллекция, используйте цикл for; если коллекции нет, а имеется лишь условие продолжения, используйте цикл while. При сомнении начните с цикла for; цикл while добавляйте в тех случаях, когда использование цикла for выглядит неестественным.

Операторы break и continue

Оператор break немедленно завершает выполнение текущего цикла. Код, который в теле цикла расположен ниже оператора break, на данной итерации не выполняется. Последующие итерации также не выполняются.

Оператор continue не выполняет оставшуюся часть тела цикла на текущей итерации, однако не завершает цикл полностью. После оператора continue выполнение переходит к следующему элементу в цикле for либо к повторной проверке условия в цикле while.

modes = ["STABILIZE", "LOITER", "GUIDED", "AUTO", "RTL"]

print("--- continue: не печатаем STABILIZE ---")
for mode in modes:
    if mode == "STABILIZE":
        continue  # перейти к следующему mode, print ниже не выполнять
    print("see:", mode)

print("--- break: остановиться на AUTO ---")
for mode in modes:
    print("checking:", mode)
    if mode == "AUTO":
        print("found AUTO, stop search")
        break  # выходим из цикла for полностью
Ожидаемое поведение программы: в первом цикле среди строк, начинающихся с префикса «see:», не будет значения STABILIZE. Во втором цикле после того, как встретится значение AUTO, новые строки, начинающиеся с префикса «checking:», появляться не будут.
↑ К оглавлению

4. Функции: def, return, docstring

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

Зачем нужны функции

Если функции не используются, то один и тот же расчёт, например перевод сантиметров в метры, определение класса батареи или выделение режима AUTO, приходится воспроизводить повторным копированием и вставкой. Впоследствии программист исправляет такой фрагмент в одном месте и забывает исправить его в другом. Функция даёт этому расчёту одно имя и создаёт одно место, в котором выполняется правка.

Аналогия. В программе Mission Planner кнопка Write, то есть «Записать», представляет собой именованное действие с понятным входом, которым является текущая миссия, и с понятным эффектом. Функция в языке Python является собственной «кнопкой» программиста внутри кода. Эта аналогия уместна лишь до известного предела: кнопка Mission Planner выполняет множество скрытых действий, тогда как ваша функция должна быть понятной по своему имени и кратко описанной в docstring.

Синтаксис объявления функции def и оператор return

def alt_cm_to_m(alt_cm: int) -> float:
    """Перевести высоту из сантиметров в метры (учебный пример, часто встречается в MAVLink)."""
    # 100 сантиметров равны одному метру
    return alt_cm / 100.0


# Вызов функции: передаём аргумент 1530 и сохраняем результат в переменную
meters = alt_cm_to_m(1530)
print(meters)  # 15.3

Разберём объявление функции по составным частям.

  • Ключевое слово def сообщает интерпретатору, что объявляется функция.
  • Имя alt_cm_to_m обозначает функцию; желательно выбирать имя в форме глагола или указывать, какой результат возвращает функция.
  • Имя alt_cm является параметром, то есть входной величиной функции.
  • Оператор return передаёт результат вызывающему коду и завершает выполнение функции.
  • Строка, которая расположена сразу под строкой def и заключена в тройные кавычки, называется docstring; подробнее о ней говорится в следующем подразделе.
Оператор return не является оператором print. Оператор print выводит текст на экран для человека. Оператор return передаёт значение внутрь программы: полученное значение можно сохранить в переменную, передать в другую функцию или проверить с помощью оператора if. Функция может одновременно и вычислять, и печатать, однако для обучения полезно на первых порах разделять эти две роли.
def add(a, b):
    return a + b

x = add(2, 3)   # переменная x получит значение 5
print(x)

Если функция не содержит оператора return, то результатом её вызова является значение None:

def only_print(msg):
    print(msg)
    # оператор return отсутствует

result = only_print("hello")
print(result)  # None

Документирующая строка (docstring)

Docstring представляет собой краткое описание того, что делает функция; оно располагается сразу под строкой def и заключается в тройные кавычки. Это описание читают и люди, и инструменты разработки. На начальном этапе обучения достаточно одного-трёх предложений на русском языке.

def format_voltage(voltage_v: float) -> str:
    """Вернуть строку напряжения с двумя знаками после запятой."""
    return f"{voltage_v:.2f} V"
↑ К оглавлению

5. Аргументы и значения по умолчанию

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

Три способа передать данные в функцию

Первый способ. Передача по позиции, то есть по порядку.

Программист записывает значения в том же порядке, в котором параметры перечислены в объявлении def. Первое переданное значение попадает в первый параметр, второе значение — во второй параметр и так далее.

def describe(name, volts):
    return f"{name}: {volts}"

# Первое значение попадает в параметр name, второе — в параметр volts
print(describe("battery", 15.0))

Второй способ. Передача по имени параметра.

Программист явно указывает имя параметра и присваивает ему значение в форме «имя_параметра = значение». В этом случае интерпретатору не нужно сопоставлять значения по порядку: он помещает каждое значение в тот параметр, имя которого было указано.

# То же самое, но имена параметров указаны явно
print(describe(name="battery", volts=15.0))

# Порядок указания имён можно изменить — смысл вызова не нарушается
print(describe(volts=15.0, name="battery"))

Третий способ. Значение по умолчанию (default).

В заголовке объявления def параметру можно присвоить готовое значение по умолчанию в форме «параметр = значение». Если при вызове соответствующий аргумент не был передан, интерпретатор подставит значение по умолчанию. Если же аргумент был передан, будет использовано переданное значение.

def greet(who, prefix="Hello"):
    return f"{prefix}, {who}"

print(greet("pilot"))                 # Hello, pilot  (prefix взят из default)
print(greet("pilot", prefix="Privet"))  # Privet, pilot
Правило синтаксиса. В объявлении def параметры, которым задано значение по умолчанию, должны располагаться после параметров, у которых такого значения нет. В противном случае интерпретатор Python сообщит об ошибке SyntaxError.

Соберём все три способа в одной учебной функции, которая относится к батарее:

def battery_status(
    voltage_v: float,
    low_v: float = 14.4,
    critical_v: float = 14.0,
) -> str:
    """Классифицировать напряжение. Пороги являются учебными и не предназначены для реального борта."""
    if voltage_v >= low_v:
        return "OK"
    if voltage_v >= critical_v:
        return "LOW"
    return "CRITICAL"


# Передали только напряжение.
# Параметр low_v получит значение 14.4, параметр critical_v — значение 14.0 из значений по умолчанию.
print(battery_status(15.0))

# Передали все три значения явно, по именам параметров.
# Благодаря этому видно, какое значение является напряжением,
# какое — порогом low, а какое — порогом critical.
print(battery_status(voltage_v=14.2, low_v=14.5, critical_v=14.0))

Зачем следует вызывать функцию по именам аргументов

Сравним два вызова одной и той же функции.

Первый вариант — только числа, переданные по порядку.

print(battery_status(14.2, 14.5, 14.0))

Через месяц, вернувшись к этой строке, вы увидите три числа. Какое из них представляет текущее напряжение? Какое представляет порог «низкое напряжение»? Какое представляет порог «критическое напряжение»? Чтобы ответить на эти вопросы, необходимо открыть объявление функции battery_status и изучить порядок параметров. При таком способе легко переставить местами числа 14.5 и 14.0 и получить незаметную логическую ошибку.

Второй вариант — те же числа, но с указанием имён параметров.

print(battery_status(voltage_v=14.2, low_v=14.5, critical_v=14.0))

В этом случае строка вызова объясняет саму себя.

  • Запись voltage_v=14.2 означает, что текущее напряжение равно 14,2 вольта.
  • Запись low_v=14.5 означает, что порог «низкое напряжение» равен 14,5 вольта.
  • Запись critical_v=14.0 означает, что порог «критическое напряжение» равен 14,0 вольта.

Вам не требуется удерживать в памяти правило, что «второй аргумент соответствует порогу low». Такой вызов напоминает заполненную форму, в которой после каждого имени следует соответствующее значение.

Практическое правило. Один-два очевидных аргумента можно передавать по позиции, как в вызове alt_cm_to_m(1530). Как только аргументов становится несколько и они становятся похожи друг на друга, например три следующих подряд значения напряжения, следует вызывать функцию по именам аргументов. Такой способ снижает количество ошибок и облегчает возвращение к коду спустя некоторое время.
↑ К оглавлению

6. Подсказки типов на начальном уровне

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

def alt_cm_to_m(alt_cm: int) -> float:
    """cm -> m"""
    return alt_cm / 100.0

Эта запись читается следующим образом: «функция принимает значение alt_cm типа int и возвращает значение типа float».

ЗаписьСмысл
x: int ожидается целое число
x: float ожидается дробное число
x: str ожидается строка
x: bool ожидается значение True или False
-> float функция возвращает значение типа float
-> None функция не возвращает полезного значения; как правило, такая функция только печатает текст
Для начала этого достаточно. Более сложные подсказки, например list[dict[str, float]], появятся по мере необходимости. В файлах практики, имена которых начинаются с префикса k05_, уже присутствуют простые подсказки типов; заимствуйте этот стиль.
↑ К оглавлению

7. Чистая функция и побочный эффект

Этот раздел является одним из наиболее важных инженерных разделов модуля M1. Мы вернёмся к нему, когда познакомимся с командами MAVLink.

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

Побочным эффектом называется всё то, что функция выполняет сверх возврата значения. На текущем этапе это, как правило, оператор print. В дальнейшем побочным эффектом могут быть запись в последовательный порт serial, отправка данных по протоколу UDP или запрос на выполнение команды arm.

def is_above_min_alt(altitude_m: float, min_alt_m: float) -> bool:
    """Чистая функция: только сравнивает значения и возвращает bool."""
    return altitude_m >= min_alt_m


def report_alt_gate(altitude_m: float, min_alt_m: float) -> None:
    """Побочный эффект: печатает отчёт человеку.

    Позже похожая функция может отправлять данные по MAVLink.
    Сейчас важно следующее: сначала вычисляется решение (pure),
    затем выводится сообщение (side effect).
    """
    ok = is_above_min_alt(altitude_m, min_alt_m)
    if ok:
        print(f"GO: alt={altitude_m} >= min={min_alt_m}")
    else:
        print(f"STOP: alt={altitude_m} < min={min_alt_m}")


print("pure:", is_above_min_alt(12.0, 10.0))
report_alt_gate(12.0, 10.0)
report_alt_gate(3.0, 10.0)
Зачем необходимо разделять чистую функцию и побочный эффект. Чистую функцию легко проверить с помощью теста; такие проверки будут рассмотрены на занятии K11. Функцию, которая отправляет команду на борт аппарата, проверяют осторожнее и с использованием заглушек. Если же объединить в одной функции вывод текста, отправку команды и вычисления, то отладка такого кода станет затруднительной.
Напоминание курса. Ни одна из учебных функций занятия K05 не имеет права выполнять команду arm и не связана с моторами. Мы изучаем лишь структуру кода.
↑ К оглавлению

8. Типичные ошибки

ОшибкаЧто вы наблюдаетеКак следует рассуждать
Программист забывает изменять переменную в цикле while Программа перестаёт отвечать Каждая итерация должна приближать момент выхода из цикла
Программист ожидает результат, но внутри функции выполняется только оператор print Снаружи функция возвращает None, либо результат кажется пустым Если результат используется далее, функция должна содержать оператор return
Оператор return расположен в середине функции, а программист ожидает, что код ниже всё равно выполнится Незаметная логическая ошибка Оператор return немедленно завершает выполнение функции
Параметр без значения по умолчанию расположен после параметра со значением по умолчанию Ошибка SyntaxError Сначала следует перечислять обязательные параметры, затем параметры со значениями по умолчанию
Имя функции не отражает её назначение Спустя некоторое время код становится трудным для чтения Имя do_stuff неудачно; имя alt_cm_to_m удачно
Функция выполняет слишком много различных задач Код становится сложным для изменения Разделите код: одна задача — одна функция
↑ К оглавлению

9. Практика

Все файлы находятся в каталоге code/M01_python/ и содержат комментарии. Запускайте их в виртуальном окружении.

Задача 5.1. Цикл while

Файл k05_task1_while_countdown.py. С помощью цикла while выполните отсчёт шагов счётчика до значения ready.

Задача 5.2. Операторы break и continue

Файл k05_task2_break_continue.py. Пропустите значение STABILIZE и остановитесь на значении AUTO.

Задача 5.3. Объявление def и оператор return

Файл k05_task3_functions_basic.py. Выполните перевод сантиметров в метры и отформатируйте значение напряжения.

Задача 5.4. Значения по умолчанию и вызов по именам

Файл k05_task4_args_defaults.py. Функция battery_status с учебными порогами. Сравните вызов, в котором значения переданы только числами, и вызов, в котором указаны имена voltage_v, low_v и critical_v.

Задача 5.5. Чистая функция и побочный эффект

Файл k05_task5_pure_vs_side_effect.py. Сначала вычислите решение, возвращающее тип bool, затем выведите отчёт.

Задача 5.6. Несколько функций для работы с телеметрией

Файл k05_task6_mission_helpers.py. Определите максимальную высоту, выполните фильтрацию по значению mode и составьте текстовую сводку.

Задача 5.7. Запись изменений в репозиторий

git add code/M01_python/k05_*.py
git commit -m "K05: while break functions args pure vs side effects"
↑ К оглавлению

10. Проверьте себя

  1. В каких случаях следует выбирать цикл for, а в каких — цикл while? Приведите по одному учебному примеру из области беспилотной авиации.
  2. Чем оператор break отличается от оператора continue?
  3. Что выполняет оператор return и чем он не является оператор print?
  4. Что представляет собой аргумент со значением по умолчанию?
  5. Чем вызов battery_status(14.2, 14.5, 14.0) хуже вызова battery_status(voltage_v=14.2, low_v=14.5, critical_v=14.0)?
  6. Что означает запись def f(x: float) -> str?
  7. Что такое побочный эффект? Почему решение «можно выполнить / нельзя выполнить» лучше вычислять отдельно от оператора print, а в дальнейшем — отдельно от отправки команды?
  8. Зачем нужен docstring для функции, которой пока пользуетесь только вы сами?
  9. Почему предпочтительнее несколько небольших функций, чем одна функция объёмом в двести строк?
↑ К оглавлению

11. Чек-лист самопроверки

  • Я записываю цикл for по списку и понимаю, что означает итерация.
  • Я записываю цикл while и умею объяснить, каким образом он завершается.
  • Я могу сформулировать полное объяснение, когда следует выбрать for, а когда while, не ограничиваясь короткой незаконченной фразой.
  • Я применяю операторы break и continue по их назначению.
  • Я объявляю функцию с помощью def, использую return и добавляю docstring.
  • Я передаю аргументы по позиции и по имени и понимаю различие между этими способами.
  • Я задаю параметрам значения по умолчанию.
  • Я читаю простые подсказки типов.
  • Я отличаю чистую функцию от функции, которая выводит текст (побочный эффект).
  • Я собрал вспомогательные функции для обработки структуры list[dict], содержащей телеметрию.
  • Я запускал файлы от k05_task1 до k05_task6 в виртуальном окружении.
  • Я записал изменения по занятию K05 в репозиторий с помощью git.
Результат: когда все пункты чек-листа выполнены, напишите сообщение K05 чек-лист закрыт. Следующим занятием является K06, посвящённое модулям, пакетам, виртуальному окружению venv и инструменту pip; на нём будет рассмотрено, как организовать проект и как устанавливать библиотеки, необходимые для работы с pymavlink.
↑ К оглавлению

12. Что дальше

  • Предыдущее занятие: K04 · Коллекции.
  • Текущее занятие: K05 · Циклы и функции (редакция 1.2).
  • Следующее занятие: K06 · Модули, пакеты, venv, pip.
  • Горизонт модуля M1: занятие K12 «CLI Fake GCS» и контрольный рубеж G1.
Изменения в редакции 1.2: текст приведён к стилю подробного объяснения; блоки «выбор между for и while» и «зачем вызывать функцию по именам аргументов» изложены полными предложениями; термины не сокращаются и не опускаются; сокращённые разговорные формулировки заменены полными. Техническое содержание и учебные примеры сохранены.
Напоминание о стиле. Если в тексте занятия или в ответе ментора встретится непонятная фраза, напишите «Не понял фразу: …». Учебный код снабжается комментариями. Стандарт оформления описан в документе docs/05_EDITOR_STYLE_GUIDE.md.
↑ К оглавлению

 

 

Пятница, 14 августа 2026
k05. Управление потоком и функции