Коротко: for у Python не рахує числа, а перебирає готову послідовність — список, рядок, діапазон. Через це range(5) дає 0, 1, 2, 3, 4, а не числа до п'яти включно. Нуль на старті й відсутнє останнє значення — дві речі, на яких спотикаються майже всі.

Цикл — перша конструкція, після якої дитина пише програму, а не послідовність команд. До нього код читається згори вниз, по рядку за раз. Після нього з'являється інша думка: нехай комп'ютер зробить це сто разів сам.

Що саме перебирає for

У записі for i in range(5) головне слово — in. Python бере щось, усередині чого є елементи, і дістає їх по черзі. Список, рядок, діапазон, рядки файлу, ключі словника — усе це послідовності, і всі поводяться однаково.

Тому for symbol in "кіт" видасть три літери, а for number in [10, 20, 30] — три числа. Лічильника Python при цьому не веде: змінна просто отримує черговий елемент. Це зовсім інша модель, ніж у мовах, де цикл складається з початку, умови й кроку, і діти, які бачили такий запис у старших родичів, спершу шукають його очима.

Назва змінної після for — довільна. Традиційне i прийшло з математики й годиться для чисел, але в коді, який читатимуть люди, краще писати по суті: for uchen in spysok_klasu зрозуміліше за for i in spysok_klasu. На заняттях ми просимо називати змінну так, щоб рядок читався вголос як речення.

range: чотири форми й одна пастка

Форми запису range()
ЗаписЩо даєКоли потрібен
range(5)0, 1, 2, 3, 4повторити дію п'ять разів
range(1, 6)1, 2, 3, 4, 5коли рахунок іде з одиниці
range(0, 10, 2)0, 2, 4, 6, 8через крок: парні, кожен третій
range(5, 0, -1)5, 4, 3, 2, 1зворотний відлік

Праве число не входить у результат ніколи. Це не примха мови: завдяки цьому range(len(spysok)) дає рівно стільки кроків, скільки елементів у списку, і остання позиція не вилітає за межі. Варто показати це на прикладі зі списком з трьох імен — тоді правило перестає бути довільним.

Окремо про від'ємний крок. Запис range(10, 0, -1) дає числа від десяти до одиниці, і нуля в ньому немає з тієї самої причини: праве число не входить. Щоб відлік закінчився нулем, потрібно range(10, -1, -1), і саме ця конструкція щоразу викликає подив.

Типова сцена на занятті: дитина пише зворотний відлік ракети й отримує «1, 0, Пуск» замість «3, 2, 1, Пуск». Правка займає секунду. Розуміння, чому межа працює саме так, — хвилин п'ять. Ці п'ять хвилин потім економлять години на складніших задачах зі зрізами списків.

Коли потрібен не елемент, а його номер

Школярі часто пишуть for i in range(len(spysok)), щоб дістатися і до номера, і до значення. Працює, але читається гірше за enumerate: запис for nomer, znachennya in enumerate(spysok) віддає обидва одразу й не дає помилитися з індексом.

Якщо нумерація має починатися з одиниці — наприклад, для списку учнів на екрані, — enumerate приймає другий аргумент: enumerate(spysok, 1). Це дрібниця, але вона прибирає з коду вічне nomer + 1, у якому легко помилитися.

Коли треба пройти двома списками одночасно, стане в пригоді zip: for imya, bal in zip(imena, baly). Він зупиняється на коротшому зі списків — це варто перевірити одразу, інакше частина даних тихо загубиться.

Словники перебираються інакше

Простий for key in slovnyk дає тільки ключі. Щоб одразу отримати пару, потрібен for key, value in slovnyk.items(). Діти, які пропустили цю деталь, зазвичай пишуть slovnyk[key] усередині циклу — працює, але довше й заплутаніше.

Вкладені цикли

Цикл усередині циклу — наступний рівень, і він з'являється природно: таблиця множення, поле для гри, сітка пікселів. Зовнішній цикл відповідає за рядки, внутрішній — за стовпці, і саме цей порядок діти плутають найчастіше.

Корисно одразу проговорити ціну. Два вкладені цикли по сто кроків — це десять тисяч дій, три вкладені по сто — мільйон. На маленьких прикладах різниця непомітна, але звичка рахувати кроки стане в пригоді, коли програма почне гальмувати.

break, continue і дивне for-else

Два слова керують ходом циклу. break виходить із нього повністю, continue пропускає лише поточний крок і йде до наступного. Плутанина між ними дає найтихішу категорію помилок: програма працює, просто результат не той.

Є ще конструкція, якої немає в більшості мов: else після for. Блок виконується, якщо цикл дійшов до кінця без жодного break. Найчастіше він потрібен у пошуку: перебрали весь список, нічого не знайшли — повідомили про це. Зустрівши таке в чужому коді, дитина зазвичай вирішує, що це помилка.

Чотири помилки, які повторюються

  • Зміна списку прямо під час перебору. Елементи зсуваються, частина пропускається мовчки. Безпечніше збирати новий список, а не правити той, яким ідеш.
  • Відступ. Тіло циклу в Python задає саме відступ, і рядок, зсунутий назад, виконається один раз після циклу, а не всередині. Помилка IndentationError — найчастіша з перших тижнів.
  • Забутий input усередині циклу. Якщо запит винесено назовні, програма питає один раз, а далі крутить ту саму відповідь.
  • Нескінченний цикл через while там, де вистачило б for. Коли кількість кроків відома наперед, for надійніший: він не вміє зациклитися.

Як читати помилку, коли цикл не працює

Python майже завжди називає рядок, на якому спіткнувся, і тип проблеми. У циклах трапляються три повідомлення. IndentationError означає, що відступи не збігаються — зазвичай змішалися табуляція й пробіли, і на вигляд рядок стоїть правильно. TypeError: 'int' object is not iterable з'являється, коли після in поставили число замість range від нього. IndexError: list index out of range — вихід за межі списку, майже завжди через зайву одиницю в range.

Привчати читати останній рядок повідомлення варто з першого ж заняття. Дитина, яка цього не робить, кличе викладача на кожну червону пляму; дитина, яка читає, за місяць починає виправляти половину помилок сама. Різниця у швидкості навчання після цього стає помітною неозброєним оком.

Коли цикл з'являється на курсі

На курсі Python для 10–14 років цикл іде на другому-третьому занятті — рівно тоді, коли перші програми стають довшими за екран і переписувати однакові рядки набридає самій дитині. Момент вдалий: мотивація приходить із задачі, а не з пояснення.

У старшій групі 14–18 років той самий матеріал проходять швидше й одразу переходять до генераторів списків — короткого запису, який робить те саме в один рядок. Але порядок зберігається: спершу звичайний цикл, потім скорочення. Зворотний шлях, коли підліток вивчив скорочення й не розуміє, що під ним, закінчується списуванням без розуміння.

Про те, у якому віці все це має сенс починати, ми писали окремо — у матеріалі з якого віку вчити Python дитину.