Глава 12 Цикл for

⏱️ Час на опанування теми: 15 хвилин

🤷 Для чого ми це вивчаємо:

🔑 Результати навчання:

  • Розуміння що таке програма, додаток та програмне забезпечення
  • Розуміння що таке алгоритм, кодування та програмування

🎈 Увага: Наразі ця глава знаходиться у стані активної розробки і ймовірно буде змінюватись і доповнюватись!


У цій главі ми познайомимось з…


Ми знов почнемо з проблеми. У нас є список з іменами усіх Месників, які були членами з самого початку:

avengers = [
    "iron man", "captain america", "hulk", "thor", "black widow", "hawkeye"
]

Проте усі імена почитаються з маленьких літер, що не ок. Нам треба роздрукувати ці всі імена з великих літер. У Додатку D ми обговорюємо метод об’єктів str, який називається .title(). Цей метод робить перші літери усіх слів в строці великими:

sentance = "show me how title method works"
sentance.title()
## 'Show Me How Title Method Works'

Все круто, але такого метода у списків немає. Давайте переконаємось у цьому:

avengers.title()
## 'list' object has no attribute 'title'

Але такий метод є у кожного елемента списку. Давайте дивитись:

avengers[0].title()
## 'Iron Man'

З цим можна працювати – ми можемо перелічити усі елементи цього списку та застосувати .title() до них:

print(avengers[0].title())
## Iron Man
print(avengers[1].title())
## Captain America
print(avengers[2].title())
## Hulk
print(avengers[3].title())
## Thor
print(avengers[4].title())
## Black Widow
print(avengers[5].title())
## Hawkeye

І так кожного разу нам треба буде писати ці шість рядків коду, якщо ми захочемо щось зробити з елементами. І це тільки шість рядків коду, а якщо ми візьмемо усіх супергероїв Marvel, то це буде вже не весело.

12.1 Синтаксис цикла for

Програмування повинно бути фаном, тому програмісти вигадали таку штуку як цикл. Цикл – це механізм виконання одно і того ж коду певну кількість разів. Одним з таких циклів є for.

Якщо ми представимо цей цикл у вигляді блок-схеми, то це буде виглядати ось так:

Спочатку, давайте подвивимось який саме код ми повторюємо. Це є print(_____.title()), де _____ – це певний елемент списку. Тепер нам треба сказати Python, що треба цей рядок виконати для кожного елемента в нашому списку. Тобто, “для елемента в списку, роздрукуй …”, що англійською буде “for element in list, print…”. Ви не повірете, але у Python цей код буде виглядати майже як переклад на англійську:

for element in avengers: 
    print(element.title())
## Iron Man
## Captain America
## Hulk
## Thor
## Black Widow
## Hawkeye

Розберемо ж ключові частини цього коду:

  • for: ключове слово яке свідчить про те, що далі буде цикл for
  • element: ім’я змінної, яка по черзі буде приймати кожне значення зі списку avengers
  • in: оператор
  • avengers: список, кожен елемент з якого буде присовєний до element
  • :: двокрапка, що позначає початок блоку коду
  • print(element.title()): тіло циклу, тобто команди котрі будуть виконуватись певну кількість разів

Частини for, in, : є незмінними, а все інше ми можемо змінити. Ось ім’я element може бути будь яким валідним ім’ям, наприклад ви можете зустріти item. Якщо елементи списка є відтворення об’єкту з фізичного світу, то ми можемо використати назву об’єкта для імені. Це підвищить читабельність та зрозумілість коду. Наприклад, тут є сенс замість element використати superhero, тому що кожен елемент – ім’я супергероя:

for superhero in avengers: 
    print(superhero.title()) # замість element тепер ми використовуємо superhero
## Iron Man
## Captain America
## Hulk
## Thor
## Black Widow
## Hawkeye

Як і у випадку умовного переходу if, блок коду який йде після рядку з ключовим словом for, повинен починатися з відступу, який складається зазвичай з чотирьох пробілів. Цей блок коду може мати скільки завгодно рядків коду.

Давайте ще раз подивимось на те, як сконструювати цикл for:

Тепер ми будемо інтерпретувати, що ж саме коїться в цьому коді. Python виконає тіло циклу (блок коду з відступом) стільки разів, скільки елементів в нашому списку. Кожноме “проходження” або виконання називається ітерацією. При кожній ітерації, змінна element буде отримувати значення елементів зі спуску по черзі. Іншими словами, при першій ітерації, element прийме значення sequence[0], при другій ітерації – sequence[1], і так далі.

Якщо ми “розгорнимо” цей цикл, то він буде виглядати приблизно ось так:

# перша ітерація 
element = avengers[0]
print(element.title())

# друга ітерація 
element = avengers[1]
print(element.title())

# третя ітерація 
element = avengers[2]
print(element.title())

# і так до останнього елементу

До речі, тіло циклу може містити будь які інструкції, вирази тощо. Наприклад, ми можемо помістити туди умовний перехід if. Прикладом може бути ситуація, коли у нашому списку перемішані додатні та від’ємні числа, і нам треба знайти суму тільки додатніх чисел. Ми можемо використати цикл for, у якому ми будемо перевіряти кожен елемент на додатність:

numbers = [-2, 7, -2, 5, -2, -10]

total = 0 # змінна, в якій ми будемо накоплювати суму

for item in numbers: 
    if (item > 0): # код нижче буде виконаний тільки якщо item > 0
        total = total + item 

total
## 12

Якщо тіло нашого циклу досить маленький, то ми можемо використати так звані включення. Це не супер важлива тема, тому ми залишили її у Додатку G.

12.2 Використовуємо цикл for на кортежах, словниках та множинах

Цикли for працюють не тільки з list, а й також з кортежами tuple. Давайте надрукуємо квадрат кожного елемента в кортежі:

for num in (2, 5, 6, 10):
    print(num ** 2)
## 4
## 25
## 36
## 100

Ви також мабудь звернули увагу на те, що нам не обов’зково використовувати змінну в циклі for, ми також можемо використати вираз, який повертає кортеж.

Зі словниками трохи складніше. У нас є ключі і значення, які доступ до яких ми можемо отримати за допомогою методів .keys() та .values(), відповідно (дивись Главу 9, якщо не пам’ятаєш). Якщо в списках та кортежах, ми “йшли” по елементам, то в випадку словників ми можемо “пройтись” або по ключам або по значенням. Для цього, замість просто імені об’єкту який містить словник, треба зазначити ім’я плюс той метод, який нас цікавить.

Нижче ми створюємо новий словник з найкрутішими TikToker’ами та кількістю підписників (у мільйонах) і спочатку роздрукуємо їх імена, тобто ключі:

tiktokers = {
    "Khabane Lame": 157.3,
    "Charli D'Amelio": 150.5,
    "Bella Poarch": 92.7
}

for name in tiktokers.keys(): # зверніть увагу на вкористання методу .keys()
    print(name)
## Khabane Lame
## Charli D'Amelio
## Bella Poarch

Тепер давайте роздрукуємо кількість підписників, тобто значення:

for followers in tiktokers.values(): # зверніть увагу на вкористання методу .values()
    print(followers * 1000000)
## 157300000.0
## 150500000.0
## 92700000.0

Із множинами навіть не треба використовувати ніякі методи – цикл пройде по усім значенням:

egg = {"egg white", "yolk"}
for part in egg: 
    print(part)
## egg white
## yolk

12.3 Використовуємо range() та enumerate() для зміни елементів списків

Цикл for нам знадобиться також, коли ми захочемо змінити значення елементів. Нажаль, ми не можемо просто змінювати змінну яка приймає значення елементів при кожній ітерації. Це дійсно змінить цю змінну, але не змінить значення елементів списку.

У прикладі нижче, ми намагаємось замінити елементи списку квадратами їхніх значень, але так просто воно це не спрацює:

numbers = [3, 2, 3, 4]
for num in numbers:
    num = num ** 2 # в цьому рядку ми тільки змінюємо значення num

numbers # як ми бачимо, значення numbers не змінились
## [3, 2, 3, 4]

Для цього нам треба використати маленький трюк: ми створимо новий список, який міститиме індекси усіх елементів numbers. Нагадуємо що індекси – це порядковий номер елемента і ми їх проходили у Главі 7). Давайте спочатку спробуємо надрукувати елементи, як ми це робили до цього:

numbers = [3, 2, 3, 4]
indexes = [0, 1, 2, 3] # список, який містить індекси елементів списка numbers

for i in indexes:
    print(numbers[i])
## 3
## 2
## 3
## 4

Давайте розгорнемо цей цикл:

# перша ітерація
i = 0
print(numbers[i]) # тобто print(numbers[0])
## 3
# друга ітерація
i = 1
print(numbers[i]) # тобто print(numbers[1])
## 2

# і так далі

Тепер ми можемо просто змінити значення елементів за допомогою numbers[i] = numbers[i] ** 2:

numbers = [3, 2, 3, 4]
indexes = [0, 1, 2, 3] # список, який містить індекси елементів списка numbers

for i in indexes:
    numbers[i] = numbers[i] ** 2


numbers
## [9, 4, 9, 16]

До речі, використовувати назву i для змінної індексів цикла for – це класика, тому що i – це перша буква слова index.

Йдемо далі. Наш вектор numbers мав тільки чотири елемента, тому нам не складно було прописати список indices. Це буде трохи складно, як що список буде мати 1000 елементів. Тому у Python є дуже корисна фунцкія range(), яка генерує послідовність чисел. За замовчанням, range() згенерує послідовність з нуля і до числа, яке зазначено між дужками:

for i in range(4):
    print(i)
## 0
## 1
## 2
## 3

Це як раз те що нам потрібно. Залишилось порахувати скільки елементів в списку за допомогою фунцкії len() і підставити це число у range():

numbers = [3, 2, 3, 4]
n = len(numbers) # довжина списку numbers

for i in range(n): # або замість range(n) можна зразу ж підставити range(len(numbers))
    numbers[i] = numbers[i] ** 2

numbers
## [9, 4, 9, 16]

Існує більш ефективний спосіб – це фунцкія enumerate(). Вона дозволяє отримати доступ і до елемента і до індекса одночасно. Різниця тільки в тому, що до in треба зазначити дві змінні через кому – першу для індексу і другу для елемента. Функція enumerate() працює трохи швидше ніж трюк з range(). Давайте подивимось приклад:

numbers = [3, 2, 3, 4]

for i, num in enumerate(numbers):
    numbers[i] = numbers[i] ** 2

numbers
## [9, 4, 9, 16]

Ми пропрацюємо обидва методи більш детально у вправах, тому що володіння циклами – це скоріш навик ніж знання.

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

Як ми дізнались до цього, ми можемо записати будь які інструкції в тіло цикла, навіть інший цикл. Це як раз те, що ми зараз зробимо:

for i in [1, 2]: # зовнішній цикл
    for j in [3, 4]: # внутрішній цикл
        print((i, j))
## (1, 3)
## (1, 4)
## (2, 3)
## (2, 4)

При першій ітерації у зовнішньому циклі, тобто коли i має значення 1, внутрішній цикл проходить обидві ітерації, тобто j приймає спочатку 3, а потім 4. І так само при другій ітерації зовнішнього циклу (коли i є 2): j прийме значення 3 на першій ітерації, та 4 на другій. Як завжди, ми можемо розгорнути цей цикл:

# перша ітерація зовнішнього циклу
i = 1
# - перша ітерація внутрішнього циклу
j = 3
print((i, j))
## (1, 3)
# - друга ітерація внутрішнього циклу
j = 4
print((i, j))
## (1, 4)
# друга ітерація зовнішнього циклу
i = 2
# - перша ітерація внутрішнього циклу
j = 3
print((i, j))
## (2, 3)
# - друга ітерація внутрішнього циклу
j = 4
print((i, j))
## (2, 4)


🤸 Вправи
1. У наступних рядках відсутні фрагменти коду замінені на квадратні дужки:
# Список тварин у лісі
animals = ["ведмідь", "вовк", "лисиця", "заєць", "сова"]

for [  ] in [  ]:
   [  ] ([  ])
Перетягніть відсутні фрагменти коду у правильному порядку, щоб завершити програму.
animal
print
animals
animal
2. Цикл for можна використовувати з:
3. Чи можна в тіло цикла додати інший цикл? Якщо так, то скільки?
4. Перетягніть код відповідно до ф-ції, яку він виконує 👾:
for i in range(1, 11): print(i)
for num in range(2, 11, 2): print(num)
sum = 0 for num in range(1, 11): sum += num print(sum)
fruits = ['яблуко', 'банан', 'апельсин'] for fruit in fruits: print(fruit)
Генерує числа числа від 1 до 10
Генерує парні числа від 2 до 10
Рахує суму чисел від 1 до 10
Друкує елементи масиву fruits