Доступ к индексу в циклах for? - PullRequest
3105 голосов
/ 07 февраля 2009

Как получить доступ к самому индексу для списка, подобного следующему?

ints = [8, 23, 45, 12, 78]

Когда я зацикливаюсь через него с помощью цикла for, как мне получить доступ к индексу цикла, в данном случае от 1 до 5?

Ответы [ 19 ]

5329 голосов
/ 07 февраля 2009

Использование дополнительной переменной состояния, такой как индексная переменная (которую вы обычно используете в таких языках, как C или PHP), считается непифоническим.

Лучшим вариантом является использование встроенной функции enumerate(), доступной как в Python 2, так и в 3:

for idx, val in enumerate(ints):
    print(idx, val)

Подробнее PEP 279 .

658 голосов
/ 21 января 2015

Как использовать цикл for, как мне получить доступ к индексу цикла, в данном случае от 1 до 5?

Используйте enumerate, чтобы получить индекс для элемента при итерации:

for index, item in enumerate(items):
    print(index, item)

И обратите внимание, что индексы Python начинаются с нуля, так что вы получите от 0 до 4 с вышеуказанным. Если вы хотите считать от 1 до 5, сделайте следующее:

for count, item in enumerate(items, start=1):
    print(count, item)

Unidiomatic управления потоком

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

index = 0            # Python's indexing starts at zero
for item in items:   # Python's for loops are a "for each" loop 
    print(index, item)
    index += 1

Или в языках, где нет цикла for-each:

index = 0
while index < len(items):
    print(index, items[index])
    index += 1

или иногда чаще (но неидиоматически) встречается в Python:

for index in range(len(items)):
    print(index, items[index])

Использование функции перечисления

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

for index, item in enumerate(items, start=0):   # default is zero
    print(index, item)

Этот пример кода довольно хорошо является каноническим примером различия между кодом, идиоматическим для Python, и кодом, которого нет. Идиоматический код является сложным (но не сложным) Python, написанным так, как он был предназначен для использования. Разработчики языка ожидают идиоматического кода, что означает, что обычно этот код не только более читабелен, но и более эффективен.

Получение подсчета

Даже если вам не нужны индексы по ходу работы, но вам нужно количество итераций (иногда желательно), вы можете начать с 1, а последним числом будет ваш счет.

for count, item in enumerate(items, start=1):   # default is zero
    print(item)

print('there were {0} items printed'.format(count))

Счет, кажется, больше того, что вы намереваетесь просить (в отличие от индекса), когда вы сказали, что хотите от 1 до 5.


Разбивка - пошаговое объяснение

Чтобы разбить эти примеры, скажем, у нас есть список элементов, которые мы хотим перебрать с индексом:

items = ['a', 'b', 'c', 'd', 'e']

Теперь мы передаем эту итерацию для перечисления, создавая объект перечисления:

enumerate_object = enumerate(items) # the enumerate object

Мы можем извлечь первый элемент из этой итерации, который мы бы получили в цикле с помощью функции next:

iteration = next(enumerate_object) # first iteration from enumerate
print(iteration)

И мы видим, что мы получаем кортеж 0, первый индекс и 'a', первый элемент:

(0, 'a')

мы можем использовать то, что называется " последовательность распаковки ", чтобы извлечь элементы из этого двух кортежа:

index, item = iteration
#   0,  'a' = (0, 'a') # essentially this.

и когда мы проверяем index, мы обнаруживаем, что это относится к первому индексу, 0, а item относится к первому элементу, 'a'.

>>> print(index)
0
>>> print(item)
a

Заключение

  • Индексы Python начинаются с нуля
  • Чтобы получить эти индексы из итерируемого при его итерации по нему, используйте функцию перечисления
  • Использование перечисления идиоматическим способом (вместе с распаковкой кортежей) создает код, который более читабелен и удобен в обслуживании:

Так сделайте это:

for index, item in enumerate(items, start=0):   # Python indexes start at zero
    print(index, item)
122 голосов
/ 27 мая 2014

Довольно просто запустить его с 1, отличного от 0:

for index, item in enumerate(iterable, start=1):
   print index, item

Примечание

Важный совет, хотя и немного вводящий в заблуждение, поскольку index здесь будет tuple (idx, item). Хорошо идти.

80 голосов
/ 07 февраля 2009
for i in range(len(ints)):
   print i, ints[i]
41 голосов
/ 15 августа 2017

Как правило, в Python есть несколько способов сделать это. Во всех примерах предположим: lst = [1, 2, 3, 4, 5]

1. Использование перечисления ( считается наиболее идиоматическим )

for index, element in enumerate(lst):
    # do the things that need doing here

По моему мнению, это также самый безопасный вариант, потому что исключена вероятность перехода в бесконечную рекурсию. И элемент, и его индекс хранятся в переменных, и нет необходимости писать дополнительный код чтобы получить доступ к элементу.

2. Создание переменной для хранения индекса ( с использованием for)

for index in range(len(lst)):   # or xrange
    # you will have to write extra code to get the element

3. Создание переменной для хранения индекса ( с использованием while)

index = 0
while index < len(lst):
    # you will have to write extra code to get the element
    index += 1  # escape infinite recursion

4. Всегда есть другой способ

Как объяснялось ранее, есть другие способы сделать это, которые не были объяснены здесь, и они могут даже применить больше в других ситуациях. например , используя itertools.chain с for. Он обрабатывает вложенные циклы лучше, чем другие примеры.

22 голосов
/ 07 февраля 2009

Старомодный способ:

for ix in range(len(ints)):
    print ints[ix]

Понимание списка:

[ (ix, ints[ix]) for ix in range(len(ints))]

>>> ints
[1, 2, 3, 4, 5]
>>> for ix in range(len(ints)): print ints[ix]
... 
1
2
3
4
5
>>> [ (ix, ints[ix]) for ix in range(len(ints))]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> lc = [ (ix, ints[ix]) for ix in range(len(ints))]
>>> for tup in lc:
...     print tup
... 
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
>>> 
18 голосов
/ 04 августа 2016

Самый быстрый способ получить доступ к индексам списка в цикле в Python 2.7 - это использовать метод диапазона для небольших списков и метод перечисления для средних и больших списки размеров.

Пожалуйста, смотрите различные подходы , которые можно использовать для перебора списка и значения индекса доступа и их метрики производительности (которые, я полагаю, будут полезны для вас) в примерах кода ниже:

from timeit import timeit

# Using range
def range_loop(iterable):
    for i in range(len(iterable)):
        1 + iterable[i]

# Using xrange
def xrange_loop(iterable):
    for i in xrange(len(iterable)):
        1 + iterable[i]

# Using enumerate
def enumerate_loop(iterable):
    for i, val in enumerate(iterable):
        1 + val

# Manual indexing
def manual_indexing_loop(iterable):
    index = 0
    for item in iterable:
        1 + item
        index += 1

См. Показатели производительности для каждого метода ниже:

from timeit import timeit

def measure(l, number=10000):
print "Measure speed for list with %d items" % len(l)
print "xrange: ", timeit(lambda :xrange_loop(l), number=number)
print "range: ", timeit(lambda :range_loop(l), number=number)
print "enumerate: ", timeit(lambda :enumerate_loop(l), number=number)
print "manual_indexing: ", timeit(lambda :manual_indexing_loop(l), number=number)

measure(range(1000))
# Measure speed for list with 1000 items
# xrange:  0.758321046829
# range:  0.701184988022
# enumerate:  0.724966049194
# manual_indexing:  0.894635915756

measure(range(10000))
# Measure speed for list with 100000 items
# xrange:  81.4756360054
# range:  75.0172479153
# enumerate:  74.687623024
# manual_indexing:  91.6308541298

measure(range(10000000), number=100)
# Measure speed for list with 10000000 items
# xrange:  82.267786026
# range:  84.0493988991
# enumerate:  78.0344707966
# manual_indexing:  95.0491430759

В результате, использование метода range является самым быстрым из списка с 1000 наименованиями. Для списка размером> 10 000 наименований enumerate является победителем.

Добавление некоторых полезных ссылок ниже:

12 голосов
/ 25 мая 2015

Прежде всего, индексы будут от 0 до 4. Языки программирования начинают считать с 0; не забывайте об этом, иначе вы встретите исключение индекса за пределами границ. Все, что вам нужно в цикле for, это переменная, считающая от 0 до 4, например:

for x in range(0, 5):

Имейте в виду, что я написал от 0 до 5, потому что цикл останавливается за одно число до макс. :)

Чтобы получить значение индекса, используйте

list[index]
9 голосов
/ 25 мая 2015

Вы можете сделать это с помощью этого кода:

ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
    index +=1
    print index, value

Используйте этот код, если вам нужно сбросить значение индекса в конце цикла:

ints = [8, 23, 45, 12, 78]
index = 0

for value in (ints):
    index +=1
    print index, value
    if index >= len(ints)-1:
        index = 0
9 голосов
/ 05 мая 2012

Согласно этому обсуждению: http://bytes.com/topic/python/answers/464012-objects-list-index

Итерация счетчика циклов

В текущей идиоме зацикливания индексов используется встроенная функция range:

for i in range(len(sequence)):
    # work with index i

Цикл по обоим элементам и индексам может быть достигнут либо с помощью старой идиомы, либо с помощью новой встроенной функции zip:

for i in range(len(sequence)):
    e = sequence[i]
    # work with index i and element e

или

for i, e in zip(range(len(sequence)), sequence):
    # work with index i and element e

через http://www.python.org/dev/peps/pep-0212/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...