2.12. Циклы¶
Цикл многократно выполняет один и тот же блок кода. В Python есть две формы: while, который продолжается, пока условие остаётся истинным, и for, который обходит элементы последовательности.
while продолжает проверять условие; for обходит последовательность, пока она не исчерпана.¶
2.12.1. Циклы while¶
Цикл while проверяет своё условие перед каждой итерацией и выполняет тело, пока проверка не станет ложной:
count = 0
while count < 5:
print(count)
count += 1
Вывод:
0
1
2
3
4
Если условие истинно в начале и никогда не становится ложным, цикл выполняется бесконечно. while True: – это стандартная идиома для основного цикла, из которого выходят явно с помощью break:
while True:
step()
if done():
break
2.12.2. Циклы for¶
Цикл for обходит элементы итерируемого объекта – списка, кортежа, строки, байтов, словаря или любого другого объекта, поддерживающего итерацию:
for fruit in ["apple", "banana", "cherry"]:
print(fruit)
Вывод:
apple
banana
cherry
Та же форма работает со строкой, где каждый элемент – это строка из одного символа:
for letter in "OpenMV":
print(letter)
Вывод:
O
p
e
n
M
V
Итерация словаря напрямую возвращает его ключи в порядке вставки:
for key in {"a": 1, "b": 2}:
print(key)
Вывод:
a
b
При каждом проходе переменная цикла (fruit, letter, key) связывается со следующим элементом. После завершения цикла переменная сохраняет значение из последней итерации.
2.12.3. range¶
Для циклов по числовому диапазону используйте range():
range(stop)– 0, 1, …, stop - 1.range(start, stop)– start, start + 1, …, stop - 1.range(start, stop, step)– с заданным шагом (отрицательные значения отсчитывают вниз).
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 8, 2): # 2, 4, 6
print(i)
for i in range(10, 0, -1): # 10, 9, ..., 1
print(i)
range() генерирует значения лениво – он не строит список в памяти. Чтобы получить настоящий list, оберните его: list(range(10)).
2.12.4. enumerate¶
Когда циклу нужны и индекс, и элемент, enumerate() выдаёт пары (index, item):
for i, name in enumerate(["a", "b", "c"]):
print(i, name)
# 0 a
# 1 b
# 2 c
Начните индекс не с нуля, передав второй аргумент: enumerate(items, start=1).
2.12.5. zip¶
Чтобы обходить два (или более) итерируемых объекта синхронно, используйте zip(). Он выдаёт по одному кортежу на каждую позицию и останавливается на самом коротком из входных данных:
names = ["alice", "bob", "carol"]
scores = [88, 92, 70]
for name, score in zip(names, scores):
print(name, score)
Вывод:
alice 88
bob 92
carol 70
2.12.6. Встроенное присваивание с :=¶
Оператор моржа := – это присваивание, которое одновременно является выражением. Он связывает имя и вычисляется в то же значение в один и тот же момент. В цикле while это сворачивает распространённый шаблон «прочитать, проверить, тело» в одну строку:
# without walrus
value = next_value()
while value is not None:
process(value)
value = next_value()
# with walrus
while (value := next_value()) is not None:
process(value)
Обе формы делают одно и то же. Используйте :=, когда дублирование присваивания действительно вредит читаемости; не используйте его просто ради хитрости. Скобки обязательны в большинстве позиций, чтобы выражение оставалось однозначным.