← назад к разделу

Выборочная проверка — компромисс: посмотрели пять записей из пятисот и надеемся, что остальные такие же. Цикл убирает этот компромисс: проверить все пятьсот стоит столько же, сколько проверить одну.

for позиция in позиции: итого += цена × количество 1 × 4990 2 × 890 1 × 12990 итогонакопитель итого = 0 объявляют ДО цикла внутри — обнулялось бы на каждом круге, и в конце осталась бы последняя позиция

Каждый элемент по очереди попадает в тело цикла и прибавляется к накопителю, объявленному заранее.

Цикл по списку

живой пример

статусы = ["NEW", "PAID", "SHIPPED"]

for статус in статусы:
    print(статус)
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

Читается буквально: «для каждого статуса в статусах — напечатай статус». Переменную статус заводить заранее не нужно, цикл делает это сам, подставляя на каждом круге очередной элемент.

Тело цикла — со сдвигом вправо, как у if. Всё, что сдвинуто, повторяется; что не сдвинуто — выполнится один раз после цикла.

Накопить сумму и счётчик

Два приёма, которые закрывают большую часть задач.

живой пример

позиции = [
    {"product": "Кофемолка", "qty": 1, "price": 4990},
    {"product": "Ланчбокс", "qty": 2, "price": 890},
]

итого = 0
for позиция in позиции:
    итого = итого + позиция["qty"] * позиция["price"]

print(итого)     # 6770
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

Переменную-накопитель заводят до цикла и обнуляют — иначе на каждом круге она сбрасывалась бы. Запись итого = итого + x часто сокращают: итого += x.

Счётчик — то же самое, только прибавляют единицу:

живой пример

заказы = [
    {"id": "ord-042", "status": "PAID", "total": 4990},
    {"id": "ord-043", "status": "CANCELLED", "total": 890},
    {"id": "ord-044", "status": "PAID", "total": 1780},
]

отменённых = 0
for заказ in заказы:
    if заказ["status"] == "CANCELLED":
        отменённых += 1

print(отменённых)     # 1
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

Обратите внимание на двойной сдвиг: if внутри for, и его тело — ещё правее. Сдвиги показывают вложенность.

Цикл по словарю

По словарю тоже можно пройти — по ключам или сразу по парам:

живой пример

заказ = {"id": "ord-042", "status": "PAID", "total": 4990}

for ключ in заказ:
    print(ключ)                       # id, status, total

for ключ, значение in заказ.items():
    print(f"{ключ} = {значение}")     # id = ord-042, ...
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

items() отдаёт пары, и их разбирают в две переменные сразу. Это удобно, когда надо проверить весь ответ разом: например, что ни одно поле не пустое.

Когда нужен номер элемента

живой пример

заказы = [
    {"id": "ord-042", "status": "PAID", "total": 4990},
    {"id": "ord-043", "status": "CANCELLED", "total": 890},
    {"id": "ord-044", "status": "PAID", "total": 1780},
]

for номер, заказ in enumerate(заказы, start=1):
    print(f"{номер}. {заказ['id']}")
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

enumerate добавляет к каждому элементу его порядковый номер. Нужен он реже, чем кажется: если вы пишете for i in range(len(список)) и потом лезете по номеру — почти всегда можно проще, прямым перебором.

Остановиться раньше

живой пример

заказы = [
    {"id": "ord-042", "status": "PAID", "total": 4990},
    {"id": "ord-043", "status": "CANCELLED", "total": 890},
    {"id": "ord-044", "status": "PAID", "total": 1780},
]
искомый = "ord-043"
найден = None

for заказ in заказы:
    if заказ["id"] == искомый:
        найден = заказ
        break          # дальше искать незачем

print(найден)
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

break выходит из цикла, continue — пропускает текущий круг и идёт к следующему:

for заказ in заказы:
    if заказ["status"] == "DRAFT":
        continue       # черновики не считаем
    ...

Собрать новый список

Частая задача: из списка словарей достать одно поле.

живой пример

заказы = [
    {"id": "ord-042", "status": "PAID", "total": 4990},
    {"id": "ord-043", "status": "CANCELLED", "total": 890},
    {"id": "ord-044", "status": "PAID", "total": 1780},
]

номера = []
for заказ in заказы:
    номера.append(заказ["id"])

print(номера)
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

У Python есть короткая запись того же самого — она встречается в чужом коде, и её стоит узнавать:

живой пример

заказы = [
    {"id": "ord-042", "status": "PAID", "total": 4990},
    {"id": "ord-043", "status": "CANCELLED", "total": 890},
    {"id": "ord-044", "status": "PAID", "total": 1780},
]

номера = [заказ["id"] for заказ in заказы]
отменённые = [з for з in заказы if з["status"] == "CANCELLED"]
print(номера)
print(отменённые)
Запустить

Запуск примеров доступен в платном доступе. Там этот же код выполняется прямо в статье: редактор, запуск и проверка рядом с абзацем. Неделя бесплатно →

Это называется списковым включением. Пишите как удобнее: длинная форма понятнее, короткая компактнее.

Частые ошибки

Накопитель внутри цикла. итого = 0 по ошибке оказался внутри — на каждом круге сумма обнуляется, в конце остаётся последнее значение.

Изменение списка во время перебора. Удалять элементы из того же списка, по которому идёте, нельзя — часть элементов будет пропущена. Соберите новый список и замените им старый.

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

Что решать

Коротко

  • for элемент in список проходит по всем элементам; заводить переменную заранее не нужно.
  • Накопитель (итого = 0, счётчик = 0) объявляют до цикла, иначе он сбрасывается на каждом круге.
  • По словарю ходят через .items() — сразу пара «ключ, значение».
  • break выходит из цикла, continue пропускает круг.
  • Списковое включение [x["id"] for x in заказы] — та же работа короткой записью; знать полезно, писать — как удобнее.

Что почитать дальше

  • Функции — чтобы не копировать один и тот же цикл по всему тесту.
  • assert и ошибки — как проверка сообщает о поломке.