enumerate()是什么意思?


Answers:


513

enumerate()函数向可迭代对象添加一个计数器。

因此,对于其中的每个元素cursor,将生成一个元组(counter, element);的for环结合,要row_numberrow分别。

演示:

>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
...     print elem
... 
foo
bar
baz
>>> for count, elem in enumerate(elements):
...     print count, elem
... 
0 foo
1 bar
2 baz

默认情况下,enumerate()从开始计数,0但是如果您给它第二个整数参数,它将从该数字开始:

>>> for count, elem in enumerate(elements, 42):
...     print count, elem
... 
42 foo
43 bar
44 baz

如果要enumerate()在Python中重新实现,可以通过以下两种方法来实现。一个itertools.count()用于进行计数,另一个用于在生成器函数中手动计数:

from itertools import count

def enumerate(it, start=0):
    # return an iterator that adds a counter to each element of it
    return zip(count(start), it)

def enumerate(it, start=0):
    count = start
    for elem in it:
        yield (count, elem)
        count += 1

C实际实现更接近于后者,它的优化方式是在常见的for i, ...拆包情况下重用单个元组对象,并对计数器使用标准的C整数值,直到计数器变得太大而避免使用Python整数对象(无界)。


92

它是一个内置函数,可返回可以迭代的对象。请参阅文档

简而言之,它遍历组合在一个元组中的可迭代元素(如列表)以及索引号:

for item in enumerate(["a", "b", "c"]):
    print item

版画

(0, "a")
(1, "b")
(2, "c")

如果要遍历一个序列(或其他可迭代的事物),并且还希望有一个可用的索引计数器,这将很有帮助。如果您希望计数器从其他值(通常为1)开始,则可以将其作为第二个参数enumerate


1
如果您添加第二个变量,item则可以删除括号:D
Abdelouahab 2014年

2
Pedantic:这是一个返回迭代器而不是生成器的函数。生成器是一类特定的用户定义函数(使用yield/ yield from或生成器表达式(隐式地yield));enumerate不是发电机。对于所有与鸭子输入相关的目的没有什么区别,但是显式类型检查和Python语言文档仅将术语“生成器”用于一种目的,但没有涵盖enumerate
ShadowRanger

22

我正在阅读Brett Slatkin 的书(《Effective Python》),他展示了另一种遍历列表的方法,并且知道列表中当前项目的索引,但是他建议最好不要使用它,enumerate而应该使用它。我知道您问过枚举是什么意思,但是当我理解以下内容时,我也了解了如何enumerate遍历列表,同时又更容易了解当前项目的索引(并且更具可读性)。

list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
    letter = list_of_letters[i]
    print (i, letter)

输出为:

0 a
1 b
2 c

我也曾经做过一些事情,甚至在阅读有关该enumerate功能之前变得更加愚蠢。

i = 0
for n in list_of_letters:
    print (i, n)
    i += 1

它产生相同的输出。

但是enumerate我只需要写:

list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
    print (i, letter)

20

正如其他用户所提到的那样,enumerate是一个生成器,它在可迭代项的每个项旁边添加一个增量索引。

因此,如果您有一个要说的清单l = ["test_1", "test_2", "test_3"]list(enumerate(l))它将为您提供以下信息:[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]

现在,什么时候有用?一个可能的用例是当您要遍历项目时,并且想要跳过仅知道列表中其索引但不知道其值的特定项目(因为当时尚不知道其值)。

for index, value in enumerate(joint_values):
   if index == 3:
       continue

   # Do something with the other `value`

因此,您的代码读起来更好,因为您也可以执行常规的for循环,range但随后访问需要为其编入索引的项目(即joint_values[i])。

尽管另一个用户提到了enumerateusing 的实现zip,但我认为没有使用一种更纯净(但稍微复杂一点)的方法itertools如下:

def enumerate(l, start=0):
    return zip(range(start, len(l) + start), l)

例:

l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)

输出:

[(0,'test_1'),(1,'test_2'),(2,'test_3')]

[(10,'test_1'),(11,'test_2'),(12,'test_3')]

如评论中所提到的,这种具有范围的方法不适用于任意可迭代对象,就像原始enumerate函数一样。


另一个答案提到的原因itertools是您的range方法仅适用于容器。enumerate与任意可迭代项一起工作;如果您要迭代文件,for lineno, line in enumerate(myfile):可以使用,但是您不能这样做,range(len(myfile))因为直到达到EOF为止,长度是未知的。
ShadowRanger

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.