题 在'for'循环中访问索引?


如何访问索引本身以获取如下列表?

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

当我使用一个循环它 for 循环,如何访问循环索引,在这种情况下从1到5?


2563
2018-02-06 22:47


起源




答案:


使用附加的状态变量,例如索引变量(通常在C或PHP等语言中使用),被认为是非pythonic。

更好的选择是使用内置函数 enumerate(),在Python 2和3中均可用:

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

查看 PEP 279 更多。


4456
2018-02-06 22:52



正如Aaron在下面指出的那样,如果你想获得1-5而不是0-4,则使用start = 1。 - clozach


使用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 object),它产生索引的两项元组和原始iterable将提供的项。看起来像这样:

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']

现在我们传递这个iterable来枚举,创建一个枚举对象:

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)

519
2018-01-21 17:11





从它开始它非常简单 1 以外 0

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

注意

重要提示,虽然有点误导 index 将是一个 tuple  (idx, item) 这里。 很高兴去。


105
2018-05-27 10:04



问题是关于列表索引;因为它们从0开始,所以从其他数字开始没有什么意义,因为索引是错误的(是的,OP在问题中也说错了)。否则,调用元组的变量 index, item 只是 index 正如你所指出的那样,这是非常误导的。只是用 for index, item in enumerate(ints)。 - Antti Haapala
更好的是将括号内的索引括在(索引)中,它将适用于Python版本2和3。 - hygull


for i in range(len(ints)):
   print i, ints[i]

67
2018-02-06 22:49



那应该是 xrange 对于3.0之前的版本 - Ben Blank
不,除非需要速度,否则不应该优化。 - Georg Schölly
一个人不应该 过早 优化,虽然我同意在这种情况下,由于在2.x和3.x中使用相同的代码。
请改用枚举 - saulspatz
对于上面的Python 2.3,使用枚举内置函数,因为它更像Pythonic。 - januarvs


正如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

总有另一种方式

如前所述,还有其他方法可以做到这一点,这里没有解释,甚至可能在其他情况下应用更多。 例如 运用 itertools.chain 与...它比其他示例更好地处理嵌套循环。


34
2017-08-15 02:17



在第2点,访问 .index() 具有线性复杂性,这意味着您的循环的复杂性现在是二次的。此外,当列表包含多个相等元素时,它不起作用,因为它总是返回第一个元素的索引。 - Aristide
@Charitoo我正在删除第2点因为它真的不应该被使用 - jamylak
你可以同时进行多次枚举吗?说我希望我和J成为J> I等的指数?我想3会更好 - arviman


老式的方式:

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)
>>> 

20
2018-02-06 22:52



这是 不 错误,用于C / C ++等。它被认为是非pythonic,但也可以在python中使用。像简单的解决方案,分解为源:+ - Valor Naram
哪里说它错了? - Charlie Martin
一些蟒蛇 极端分子 会说,不要这样做。但我说这只是为了表明存在多种可能的方式 - Valor Naram


在循环中访问列表索引的最快方法 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 是赢家。

添加以下一些有用的链接:


16
2017-08-04 09:49



“可读性计数”小<1000范围内的速度差异无关紧要。在已经很小的时间指标上慢了3%。 - Surest Texas