Функція Python enumerate(), пояснена на прикладах

У цьому посібнику ви дізнаєтеся, як ефективно використовувати функцію `enumerate()` в Python.

Функція `enumerate()` у Python надає зручний спосіб отримання доступу до елементів ітераційної структури даних разом з їхніми відповідними індексами.

Спочатку розглянемо традиційний підхід доступу до елементів та їхніх індексів за допомогою звичайного циклу `for`, а потім детально вивчимо синтаксис та можливості функції `enumerate()` в Python. Під час пояснення, ми наведемо приклади коду для кращого розуміння.

Розпочнемо наше навчання.

Ітерація за допомогою циклу `for` у Python

Об’єкт Python, який дозволяє послідовний доступ до своїх елементів, називається ітерованим. Отже, списки, кортежі, словники та рядки в Python є ітерованими об’єктами.

Розглянемо приклад, де у нас є список покупок.

shopping_list = ["фрукти", "печиво", "пластівці", "протеїнові батончики", "стікери"]

У Python цикл `for` використовується для перебору елементів будь-якого ітерованого об’єкта. Синтаксис цього циклу виглядає так:

for елемент in <ітерований_об'єкт>:
    # дії над елементом

# елемент: змінна циклу
# <ітерований_об'єкт>: будь-який ітерований об'єкт Python: список, кортеж, словник, рядок і т.д.

Застосуємо цей синтаксис, щоб перебрати наш список покупок і отримати доступ до кожного елемента.

for елемент in shopping_list:
  print(елемент)

# Результат
фрукти
печиво
пластівці
протеїнові батончики
стікери

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

Ви можете використовувати додаткову змінну для відстеження індексу, збільшуючи її в тілі циклу:

індекс = 0
for елемент in shopping_list:
  print(f"індекс:{індекс}, {елемент}")
  індекс += 1

# Результат
індекс:0, фрукти
індекс:1, печиво
індекс:2, пластівці
індекс:3, протеїнові батончики
індекс:4, стікери

Однак це не найефективніший метод. Забувши оновити індекс, ви можете отримати некоректний результат:

індекс = 0
for елемент in shopping_list:
  print(f"індекс:{індекс}, {елемент}")
  # індекс не оновлюється всередині циклу

# Результат
індекс:0, фрукти
індекс:0, печиво
індекс:0, пластівці
індекс:0, протеїнові батончики
індекс:0, стікери

Ще один поширений спосіб використання циклу `for` – це комбінування з функцією `range()`, про яку ми поговоримо далі.

Використання функції `range()` для доступу до індексу

Вбудована функція `len()` у Python повертає довжину будь-якого об’єкта. Таким чином, викликавши `len(shopping_list)`, ми отримаємо довжину списку `shopping_list`, яка в нашому випадку дорівнює 5.

len(shopping_list)
# Результат: 5

Функція `range()` повертає об’єкт діапазону, який зручно використовувати в циклі. Коли ви перебираєте діапазон `range(stop)`, ви отримуєте послідовність індексів від 0 до `stop – 1`.

Якщо `stop` встановити як довжину списку, то ви отримаєте набір всіх допустимих індексів. Таким чином, використовуючи функцію `range()`, ви можете отримати доступ як до індексу, так і до відповідного елемента:

for індекс in range(len(shopping_list)):
  print(f"індекс:{індекс}, елемент: {shopping_list[індекс]}")

# Результат
індекс:0, елемент: фрукти
індекс:1, елемент: печиво
індекс:2, елемент: пластівці
індекс:3, елемент: протеїнові батончики
індекс:4, елемент: стікери

Проте цей метод не вважається найкращим ідіоматичним способом доступу до індексів та елементів одночасно в Python.

Синтаксис функції `enumerate()` в Python

Функція `enumerate()` у Python дозволяє отримати доступ до елементів ітераційного об’єкта разом з їхніми індексами. Її загальний синтаксис виглядає так:

enumerate(<ітерований_об'єкт>, start = 0)

Розглянемо параметри цього синтаксису:

  • `<ітерований_об’єкт>` є обов’язковим параметром, що представляє будь-який ітерований об’єкт Python, наприклад, список або кортеж.
  • `start` є необов’язковим параметром, що вказує індекс, з якого починається нумерація. Якщо його не вказати, за замовчуванням нумерація починається з 0.

Викликавши функцію `enumerate()` зі списком `shopping_list`, вона поверне об’єкт `enumerate`, як показано нижче:

enumerate(shopping_list)
<enumerate at 0x7f91b4240410>

Об’єкт `enumerate` не можна безпосередньо перебирати. Тому, щоб його використати, потрібно перетворити його, наприклад, в список:

list(enumerate(shopping_list))

# Результат
[(0, 'фрукти'),
 (1, 'печиво'),
 (2, 'пластівці'),
 (3, 'протеїнові батончики'),
 (4, 'стікери')]

Іншим способом доступу до елементів об’єкта `enumerate` є використання функції `next()`. в Python функція `next()` повертає наступний елемент з ітератора.

Внутрішньо функція `next()` викликає метод `__next__()` ітератора для отримання наступних елементів.

Створимо змінну `shopping_list_enum`, що містить об’єкт `enumerate`.

shopping_list_enum = enumerate(shopping_list)

Перший виклик `next(shopping_list_enum)` поверне кортеж з індексом 0 і елементом на позиції 0: (0, ‘фрукти’).

Послідовні виклики `next()` повертатимуть наступні елементи разом з їхніми індексами:

next(shopping_list_enum)
# (0, 'фрукти')
next(shopping_list_enum)
# (1, 'печиво')
next(shopping_list_enum)
# (2, 'пластівці')
next(shopping_list_enum)
# (3, 'протеїнові батончики')
next(shopping_list_enum)
# (4, 'стікери')

Якщо викликати функцію `next()` після отримання всіх елементів, виникне помилка `StopIteration`.

next(shopping_list_enum)
# ---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-16-4220f68f6c7e> in <module>()
----> 1 next(shopping_list_enum)

StopIteration:

Функція `enumerate()` повертає індекси та елементи по мірі необхідності, без попереднього обчислення. Це робить її ефективною у використанні пам’яті, особливо при роботі з великими ітерованими об’єктами.

Приклади використання функції `enumerate()`

Тепер, коли ми розглянули синтаксис функції `enumerate()`, давайте перепишемо наш цикл `for`, використовуючи її.

З попереднього розділу ми знаємо, що `enumerate()` повертає кортеж з індексом та елементом. Ми можемо розпакувати цей кортеж у дві змінні: `індекс` та `елемент`.

for індекс, елемент in enumerate(shopping_list):
  print(f"індекс:{індекс}, елемент:{елемент}")

# Результат
індекс:0, елемент:фрукти
індекс:1, елемент:печиво
індекс:2, елемент:пластівці
індекс:3, елемент:протеїнові батончики
індекс:4, елемент:стікери

Далі розглянемо, як встановити власне початкове значення індексу.

`enumerate()` з власним початковим значенням

За замовчуванням Python використовує нульову індексацію. Але, якщо вам потрібно почати нумерацію з 1 або будь-якого іншого значення, ви можете вказати це, задавши параметр `start`.

Для нашого списку `shopping_list`, якщо ви хочете почати відлік з 1, вам потрібно встановити `start = 1`.

for індекс, елемент in enumerate(shopping_list,1):
  print(f"індекс:{індекс}, елемент:{елемент}")

# Результат
індекс:1, елемент:фрукти
індекс:2, елемент:печиво
індекс:3, елемент:пластівці
індекс:4, елемент:протеїнові батончики
індекс:5, елемент:стікери

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

Помилка, якщо ви зміните порядок ітератора і початкового значення:

for індекс, елемент in enumerate(1,shopping_list):
  print(f"індекс:{індекс}, елемент:{елемент}")

# Результат
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-5dbf7e2749aa> in <module>()
----> 1 for індекс, елемент in enumerate(1,shopping_list):
      2   print(f"індекс:{індекс}, елемент:{елемент}")

TypeError: 'list' object cannot be interpreted as an integer

Щоб уникнути таких помилок, можна вказати `start` як аргумент ключового слова:

for індекс, елемент in enumerate(shopping_list, start = 1):
  print(f"індекс:{індекс}, елемент:{елемент}")

# Результат
індекс:1, елемент:фрукти
індекс:2, елемент:печиво
індекс:3, елемент:пластівці
індекс:4, елемент:протеїнові батончики
індекс:5, елемент:стікери

Ви навчилися використовувати `enumerate()` зі списками. Цю функцію можна застосовувати також до рядків, словників та кортежів.

Використання `enumerate()` з кортежами

Припустимо, що `shopping_list` є кортежем. Кортежі в Python, як і списки, є колекціями, але є незмінними. Тобто, ви не можете змінювати їх після створення, і спроба змінити елемент призведе до помилки.

У наступному коді ініціалізуємо `shopping_list` як кортеж.

shopping_list = ("фрукти", "печиво", "пластівці", "протеїнові батончики", "стікери")
type(shopping_list)
# tuple

Спроба змінити перший елемент кортежу призведе до помилки:

shopping_list[0] = 'овочі'

# Результат
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-ffdafa961600> in <module>()
----> 1 shopping_list[0] = 'овочі'

TypeError: 'tuple' object does not support item assignment

▶ Перевіримо, чи коректно працює функція `enumerate()` з кортежами.

shopping_list = ("фрукти", "печиво", "пластівці", "протеїнові батончики", "стікери")
for індекс, елемент in enumerate(shopping_list):
    print(f"індекс:{індекс}, елемент:{елемент}")

Використання `enumerate()` з рядками

Функцію `enumerate()` можна використовувати для перебору рядків, отримуючи доступ до символів та індексів одночасно.

Ось приклад:

py_str="Метелик"
for індекс, символ in enumerate(py_str):
  print(f"індекс {індекс}: {символ}")

# Результат
індекс 0: М
індекс 1: е
індекс 2: т
індекс 3: е
індекс 4: л
індекс 5: и
індекс 6: к

Як бачимо, символи рядка разом з їх індексами були виведені на екран.

Висновок 👩🏽‍💻

Підсумуємо, що ми вивчили:

  • Цикл `for` дозволяє перебирати елементи ітераційних об’єктів. Окремо можна вести облік індексу.
  • Функція `range()` дозволяє отримати діапазон дійсних індексів і використовувати їх для доступу до елементів списку.
  • Рекомендований спосіб у Python – це функція `enumerate()`, що дозволяє отримати доступ до індексів та елементів одночасно: `enumerate(ітерований_об’єкт)`. За замовчуванням нумерація починається з 0.
  • Ви можете встановити початкове значення індексу, використовуючи синтаксис `enumerate(ітерований_об’єкт, start)`.
  • `enumerate()` можна використовувати з кортежами, рядками, словниками та будь-якими ітерованими об’єктами.

Сподіваюсь, цей посібник по функції `enumerate()` був для вас корисним. Продовжуйте вивчати Python!