Что делать, если индексы при обработке последовательностей нам все-таки нужны? Python

Что делать, если индексы при обработке последовательностей нам все-таки нужны?

Одним из существенных и весьма приятных отличий Python от других языков программирования является то, что он при обработке различных последовательностей в for циклах позволяет получать доступ к элементам таких последовательностей не через соответствующие индексы, а напрямую. Это значительно упрощает код, делает его более компактным и читабельным. Однако бывают случае, когда по логике программы наряду с элементами обрабатываемых последовательностей приходится все-таки иметь дело и с индексами этих последовательностей. Наиболее очевидным в этом случае является игнор всяких там рекомендаций по стилю Python кода типа PEP 8 и использование индексов по аналогии кодинга в старом добром С:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for i in range(len(fruit_basket)):
...     print(i+1, fruit_basket[i])
...
1 вишня
2 груша
3 арбуз
4 яблоко
5 черника

Но, этот код в придачу к нарушению стиля является еще и ужасно громоздким с кучей излишних функций и переменных. Поэтому, если кроме доступа к элементам последовательности, вам действительно параллельно еще нужен какой-то их подсчет, то наиболее оправданным будет использования Python функции enumerate().

Функция enumerate() применительно к итерируемым последовательностям (структурам данных, элементы которых доступны через индекс) позволяет создать объект, генерирующий  двухэлементные кортежи, состоящие соответственно из индекса и из значения итерируемого элемента.

Давайте опробуем эту функцию на примере кода из нашего предыдущего примера:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for fruit in enumerate(fruit_basket):
...     print(fruit)
...
(0, 'вишня')
(1, 'груша')
(2, 'арбуз')
(3, 'яблоко')
(4, 'черника')

В итоге при итерации списка fruit_basket, переданного в качестве 1-го аргумента функции enumerate(), мы получили 5-ть отдельных кортежей (соответственно числу элементов в этом списке), каждый из которых содержит, как индекс соответствующего элемента, так и его значение.

Если же нам нужно изменить индекс, начиная с которого должны будут выводиться элементы нашего списка, то это можно сделать с помощью 2-го аргумента функции enumerate(), посредством ключевого слова start:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for fruit in enumerate(fruit_basket, start=1):
...     print(fruit)
...
(1, 'вишня')
(2, 'груша')
(3, 'арбуз')
(4, 'яблоко')
(5, 'черника')

Фактически, с учетом наличия 2-го аргумента в функции enumerate(), первые элементы в каждом из итерируемых кортежей (переменной fruit  внутри цикла) можно воспринимать не буквально, как индексы элементов, а просто, как порядковые номера или числа, ассоциирующиеся со значениями нашего списка.

Следовательно, при такой ситуации нам вполне может понадобится распаковывать получаемые кортежи с тем, чтобы в программу можно было получать два отдельных значения (две переменных), а именно порядковый номер элемента списка и непосредственное значение этого элемента. Для этого попробуем представить переменную fruit в виде fruit[0] и fruit[1]:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for fruit in enumerate(fruit_basket, start=1):
...     print(fruit[0], fruit[1])
...
1 вишня
2 груша
3 арбуз
4 яблоко
5 черника

Но лучше и нагляднее при распаковке кортежей все же использовать поименованные переменные следующим образом:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for fruit in enumerate(fruit_basket, start=1):
...     n, berry = fruit
...     print(n, berry, fruit)
...
1 вишня (1, 'вишня')
2 груша (2, 'груша')
3 арбуз (3, 'арбуз')
4 яблоко (4, 'яблоко')
5 черника (5, 'черника')

Примечание: Следует отметить, что при распаковке кортежей в поименованные переменные очень важно, чтобы число присваиваемых переменных (тех, что слева) строго совпадало с числом элементов, имеющихся в кортеже. В данном случае, у нас кортеж имеет два элемента. Следовательно, этому кортежу мы сопоставляем две переменные: n и berry.

Еще одной приятной особенностью Python является то, что распаковка кортежей в коде тут разрешена везде, где может происходить присваивание. Например, в строке с определением for цикла переменная слева от оператора принадлежности in также является присваиваемой. Поэтому, наши кортежи мы можем распаковывать одновременно с циклом:

>>> fruit_basket = ["вишня", "груша", "арбуз", "яблоко", "черника"]
>>> for n, berry in enumerate(fruit_basket, start=1):
...     print(n, berry)
...
1 вишня
2 груша
3 арбуз
4 яблоко
5 черника

В этом примере проиллюстрирован наиболее распространенный вариант применения функции enumerate() с одновременной распаковкой выводимых ею кортежей в поименованные переменные прямо в строке с определением цикла for.

Подытоживая все сказанное выше, при планировании обработки последовательностей посредством for цикла в Python, наверное, прежде стоит спросить себя: нужен ли мне вообще какой-то счетчик в этом цикле?- Если надобности в таком счетчики у вас нет, то просто постарайтесь использовать for цикл в максимально простой форме записи, без каких-либо излишеств. Если же у вас все-таки есть потребность в порядковых номерах или каких-либо других числах, ассоциируемых с обрабатываемыми вами последовательностями, то наилучшим способом удовлетворения таковой потребности будет использования встроенной в Python функции enumerate().

Практический Python для начинающих
Практический Python для начинающих

Станьте junior Python программистом за 7 месяцев

 7 месяцев

Возможно будет интересно

🏆 Hello, world! Python
Новичок
🏆 Hello, world!

Мы вчера запустили новый www.pylot.me. Должны были в следующую среду, но запустили вчера.

2022-10-04
Как практиковаться в Python? Python
Новичок
Как практиковаться в Python?

Для улучшения качества знаний и повышения уровня программиста, необходим постоянный практикум. Где можно это организовать самостоятельно, и как практиковаться в Python?

2022-10-19
Условные конструкции и сопоставление структурных шаблонов Шпаргалки
Новичок
Условные конструкции и сопоставление структурных шаблонов

Шпаргалка по условным конструкциям и сопоставлению структурных шаблонов

2022-11-09