Как получить доступ к индексу в Foreach петлях на Python

Часто, когда вы перебираете коллекцию предметов на Python, вам также необходимо иметь порядковый номер, связанный с каждым предметом.
Такой номер обычно называется индексом
.
Pythonический способ доступа к индексу при выполнении форач-петли
заключается в использовании встроенной функции enumerate()
.
enumerate()
добавляет индекс к каждому элементу в итерабельной коллекции.
Затем вы можете использовать встроенную функцию list()
для получения списка кортежей.
>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names))
[(0, 'Bob'), (1, 'Alice'), (2, 'John'), (3, 'Cindy')]
Обратите внимание, Python индексирование начинается с 0
.
Однако, если вы хотите начать индексацию с 1
(например, при печати данных отчёта), это тривиально достигается передачей дополнительного аргумента start
в enumerate
.
>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names), start=1)
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]
Вышеприведенный подход также полезен, если Вы печатаете данные из разных источников данных, но хотите иметь последовательный индекс по всем элементам данных.
>>> data_source1 = ['Bob', 'Alice', 'John', 'Cindy']
>>> data_source2 = ['Sarah', 'Jeff', 'Emily', 'Adam']
>>> list(enumerate(data_source1, start=1))
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]
>>> list(enumerate(data_source2, start=len(data_source1) + 1))
[(5, 'Sarah'), (6, 'Jeff'), (7, 'Emily'), (8, 'Adam')]
Обратите внимание, что вам не нужно преобразовывать объект Enumerate
в список.
Он сам по себе является итерабельным, поэтому может выполнять прямые итерации.
>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> for idx, name in enumerate(names):
... print(name)
...
Bob
Alice
John
Cindy
Могут быть и другие способы получить индекс во время итерации над коллекцией элементов,
но использование enumerate()
считается каноническим и предпочтительным.
Другой вариант - использовать отдельную переменную индекса, инициализировать ее вручную и
увеличивать вручную на каждой итерации.
Однако такой подход будет расцениваться как повторное изобретение колеса и на него будут нахмуриться.
Вот цитата из PEP 279, в которой была введена функция enumerate()
.
Эта PEP представляет новую встроенную функцию, enumerate() для упрощения обычно используемой идиомы петлирования. Она предоставляет все итерабельные коллекции с тем же преимуществом, которое функция iteritems() дает словарям – ** компактная, читаемая, надежная индексная нотация**.
Вы можете спросить, есть ли какие-нибудь последствия для производительности при использовании enumerate
в вашем коде.
Ну, вы вольны делать все измерения, но, пожалуйста, имейте в виду, что enumerate
является идиоматическим способом доступа к индексу итерабельного в “для каждого” цикла.
Идиоматический код рекомендуется мейнтейнерами Python, и они сделают всё, чтобы
заставить его работать эффективно.
А для тех из вас, кому любопытнее всего ниже, возможна реализация функции enumerate()
от вышестоящей PEP.
def enumerate(collection):
'Generates an indexed series: (0,coll[0]), (1,coll[1]) ...'
i = 0
it = iter(collection)
while 1:
yield (i, it.next())
i += 1
Сопутствующая статья - Python Loop
- Итерировать в обратном направлении в Python
- Параллельный цикл for в Python
- Уменьшение цикла в Python