Sitelet https://www.datacamp.com/zh/tutorial/python-enumerate-tutorial
跳至内容

Python enumerate 教程

了解 Python 的 enumerate 函数是什么,以及如何在日常数据科学任务中使用它。
已更新 2026年10月6日  · 10分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

Python Enumerate Tutorial Image

在本教程中,我们将讨论 Python 中的 enumerate() 函数是什么、何时使用、它创建什么样的对象、其语法以及工作原理。随后,我们将通过示例枚举 Python 中不同类型的对象,比较 enumerate() 函数的替代方案,并说明为什么它们不如 enumerate() 适合完成同一任务。

什么是 Python 中的 Enumerate,它何时使用?

enumerate() 是一个 Python 内置函数,它接受一个可迭代对象(项目集合或任何支持迭代的 Python 对象,如元组、列表、集合或字符串),在底层遍历其项目并返回一个 enumerate 对象。换句话说,该函数为可迭代对象的每个项目分配一个从 1 递增的计数,帮助我们在对该对象进行循环时跟踪迭代。创建 enumerate 对象后,我们可以将其转换为列表、元组或字典(分别使用 list()、tuple() 或 dict() 函数),或者直接遍历该对象以同时访问项目及其对应的索引。

与使用 for 循环相比,使用 enumerate() 函数在内存和计算效率方面更有优势,因为它一次就返回索引及其对应的项目。

语法

enumerate() 函数的语法非常简单:

enumerate(iterable, start=0)

其中,iterable 是我们希望枚举的可迭代对象,start 是一个可选参数,用于定义计数器的起始索引(默认情况下为典型的 Python 从 0 开始的索引)。

请注意,对可迭代对象应用 enumerate() 函数并不会改变原始对象本身。相反,如果我们希望后续还能使用结果,则应将生成的 enumerate 对象赋值给一个变量。

现在,让我们看看该函数在不同类型的 Python 可迭代对象上的工作方式。

枚举列表(List)

首先,我们将对一个 Python 列表应用 enumerate() 函数:

drinks = ['tea', 'coffee', 'cappuccino', 'lemonade']
enumerated_drinks = enumerate(drinks)
print(type(enumerated_drinks))
print(enumerated_drinks)

 输出:

<class 'enumerate'>
<enumerate object at 0x000002DC3A1145C0>

结果对象的类型是 enumerate,而当我们尝试打印它时,只是再次确认了对象类型以及它在计算机内存中的存放位置。让我们尝试像对 Python 列表或元组那样访问该对象的第一个元素:

print(enumerated_drinks[0])

 输出:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5948/1233607596.py in <module>
----> 1 print(enumerated_drinks[0])

TypeError: 'enumerate' object is not subscriptable

我们得到了一个错误,表示无法以这种方式访问 enumerate 对象的组成部分。为此,我们需要将其转换为列表、元组或字典,或者直接遍历 enumerate 对象。让我们把 enumerate 对象转换为列表:

list_enumerated_drinks = list(enumerated_drinks)
print(list_enumerated_drinks)

 输出:

[(0, 'tea'), (1, 'coffee'), (2, 'cappuccino'), (3, 'lemonade')]

现在我们清楚地看到了结果列表的内部结构:每个项目都是一个包含两个元素的元组,第一个元素是原始列表中对应项目的索引,第二个元素是项目本身。我们可以使用常见的索引方式访问该列表的元素:

print(list_enumerated_drinks[0])
print(list_enumerated_drinks[0][1])

 输出:

(0, 'tea')
tea

现在我们来把从原始列表创建的 enumerate 对象转换为元组。这一次,我们还将可选参数 start 设置为 1:

tuple_enumerated_drinks = tuple(enumerate(drinks, start=1))
print(tuple_enumerated_drinks)

 输出:

((1, 'tea'), (2, 'coffee'), (3, 'cappuccino'), (4, 'lemonade'))

上述元组的内部结构与之前创建的列表相同。不过这一次,我们把计数改成了更“贴近人类”的方式,而不是 Python 的从 0 开始的索引。

这里有一个值得一提的与 enumerate 对象相关的方法:next()。让我们重新创建 enumerated_drinks 对象,并试试这个方法:

enumerated_drinks = enumerate(drinks)
print(next(enumerated_drinks))
print(next(enumerated_drinks))
print(next(enumerated_drinks))
print(next(enumerated_drinks))
print(next(enumerated_drinks))

 输出:

(0, 'tea')
(1, 'coffee')
(2, 'cappuccino')
(3, 'lemonade')

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5948/330134057.py in <module>
      4 print(next(enumerated_drinks))
      5 print(next(enumerated_drinks))
----> 6 print(next(enumerated_drinks))

StopIteration: 

可以看到,每次在 enumerate 对象上调用该方法,都会返回其中的下一个项目(也再次验证了每个项目都是包含计数和值的 2 元组)。当所有项目都被取完后,enumerate 对象会被耗尽,再次调用 next() 方法会抛出 StopIteration 错误。确实,如果我们现在尝试把该 enumerate 对象转换为列表,会发现它是空的:

print(list(enumerated_drinks))

 输出:

[]

这意味着每次对 enumerate 对象应用 next() 方法,都会从对象中取走一个项目,因此它会一次次变小,直到完全耗尽。稍后在讨论对其应用 for 循环时,我们还会看到 enumerate 对象的这一特性。

如果您想了解更多关于 Python 列表和其他 Python 基础概念的内容,可以学习 DataCamp 的 Introduction to Python 课程。

枚举元组(Tuple)

对元组应用 enumerate() 函数与对列表的用法相同:

drinks = ('tea', 'coffee', 'cappuccino', 'lemonade')
enumerated_drinks = enumerate(drinks)
print(enumerated_drinks)

 输出:

<enumerate object at 0x000002DC3A098D40>

同样,我们得到了一个 enumerate 对象,其项目不能通过常规的 Python 索引访问。让我们把该对象转换为另一种对象,这次是字典:

dict_enumerated_drinks = dict(enumerated_drinks)
print(dict_enumerated_drinks)

 输出:

{0: 'tea', 1: 'coffee', 2: 'cappuccino', 3: 'lemonade'}

结果字典中的每个键:值对都表示对应的计数-项目配对。我们可以用常见的 Python 方式访问字典的值:

print(dict_enumerated_drinks[0])
print(dict_enumerated_drinks[3])

 输出:

tea
lemonade

如果您想更深入地学习 Python 字典和 pandas,请查看 Intermediate Python 课程。

枚举字符串(String)

由于 Python 字符串是字符序列,因此也是可迭代对象,我们同样可以为字符串创建一个 enumerate 对象:

enumerated_hello_world = enumerate('Hello, World!', start=10)
print(enumerated_hello_world)

 输出:

<enumerate object at 0x000002DC3A145C40>

与之前一样,让我们把该对象转换为列表:

list_enumerated_hello_world = list(enumerated_hello_world)
print(list_enumerated_hello_world)

 输出:

[(10, 'H'), (11, 'e'), (12, 'l'), (13, 'l'), (14, 'o'), (15, ','), (16, ' '), (17, 'W'), (18, 'o'), (19, 'r'), (20, 'l'), (21, 'd'), (22, '!')]

我们看到熟悉的 2 元组:第一个元素是字符串对应字符的计数(此处从 10 开始),第二个元素是字符本身。空格和标点符号也会被计数。

让我们重新创建 enumerated_hello_world 对象,这次不设置 start=10,并在其上应用 next 方法:

enumerated_hello_world = enumerate('Hello, World!')
print(next(enumerated_hello_world))
print(next(enumerated_hello_world))
print(next(enumerated_hello_world))
print(next(enumerated_hello_world))
print(next(enumerated_hello_world))
print(next(enumerated_hello_world))
​
# Creating a list from the remaining enumerate object
print(list(enumerated_hello_world))

 输出:

(0, 'H')
(1, 'e')
(2, 'l')
(3, 'l')
(4, 'o')
(5, ',')
[(6, ' '), (7, 'W'), (8, 'o'), (9, 'r'), (10, 'l'), (11, 'd'), (12, '!')]

在上述代码的最后一行,我们停止调用 next() 方法,并将 enumerated_hello_world 对象转换为列表。结果列表包含了在多次调用 next() 方法后,初始 enumerate 对象剩余的字符。

结合 For 循环进行枚举

最后,让我们看看 enumerate() 函数与 for 循环结合时的工作方式:

for item in enumerate(['tea', 'coffee', 'cappuccino', 'lemonade']):
  print(item)

 输出:

(0, 'tea')
(1, 'coffee')
(2, 'cappuccino')
(3, 'lemonade')

每次迭代都会返回相应的计数-项目元组,就像使用 next() 方法时一样。尽管上述代码片段中不明显,但 enumerate 对象在每次迭代时也会逐个失去其项目(即这些 2 元组)。为演示这一点,我们将以不同形式重写上面的代码,并在完成所有迭代后检查结果列表的长度:

drinks = ['tea', 'coffee', 'cappuccino', 'lemonade']
enumerated_drinks = enumerate(drinks)
​
for item in enumerated_drinks:
  print(item)
 
print(list(enumerated_drinks))

 输出: 

(0, 'tea')
(1, 'coffee')
(2, 'cappuccino')
(3, 'lemonade')
[]

与应用 next() 方法一样,遍历 enumerate 对象会逐渐将其耗尽。

不过,让我们回到前一个代码片段。如何分别访问每个 2 元组中的各个元素?为此,我们将添加一个迭代变量,对元组进行解包:

for count, drink in enumerate(['tea', 'coffee', 'cappuccino', 'lemonade']):
  print(count, drink)

 输出:

0 tea
1 coffee
2 cappuccino
3 lemonade

以上,我们为每个元组返回了两个变量:一个用于项目的计数,一个用于项目本身。

请注意,上述操作也可以在不使用 enumerate() 函数的情况下实现。例如,我们可以在循环外部引入一个计数变量,并在每次迭代时将其加 1:

count = 0
for drink in ['tea', 'coffee', 'cappuccino', 'lemonade']:
  print(count, drink)
  count += 1

 输出:

0 tea
1 coffee
2 cappuccino
3 lemonade

或者,我们可以在预定义的列表(或元组、字符串等)上组合使用 range() 和 len() 函数:

drinks = ['tea', 'coffee', 'cappuccino', 'lemonade']
for count in range(len(drinks)):
  print(count, drinks[count])

 输出:

0 tea
1 coffee
2 cappuccino
3 lemonade

此外,在这两种 enumerate() 的替代方案中,我们仍然可以将计数变量调整为非零起始值:

count = 1
for drink in ['tea', 'coffee', 'cappuccino', 'lemonade']:
  print(count, drink)
  count += 1
​
print('\n')
 
drinks = ['tea', 'coffee', 'cappuccino', 'lemonade']
for count in range(len(drinks)):
  print(count + 1, drinks[count])

 输出:

1 tea
2 coffee
3 cappuccino
4 lemonade


1 tea
2 coffee
3 cappuccino
4 lemonade

然而,与使用 enumerate() 函数相比,上述两种方法都更笨拙、容易出错(例如,我们可能会忘记在每次迭代时手动更新计数器),并且需要更多代码。因此,每当我们需要在每次迭代中同时访问可迭代对象的计数和值时,使用 enumerate() 函数都是最符合 Python 风格的做法。

总结

在本教程中,我们学习了关于 Python 中 enumerate() 函数的诸多内容,包括其多种用法、可能的替代方案,以及为什么它最终比替代方案更高效。对于大多数 Python 初学者来说,enumerate() 函数可能并不熟悉,甚至一些高级程序员也可能不了解这个非常实用的函数。

如果您想进一步了解 enumerate(),可以考虑学习 Python Data Science Toolbox (Part 2) 课程,该课程深入探讨迭代器和可迭代对象,并提供交互式练习帮助您实践新技能。此外,如果您希望掌握其他 Python 概念,您可能会对 Learn Python with DataCamp 感兴趣,其中包含多种技能与职业路径、速查表、教程、Python 认证和测评。

主题
Python
数据科学

DataCamp 的 Python 课程

课程

Python 入门

4 小时
7.1M
只需 4 小时就能掌握 Python 数据分析基础知识。 本在线课程将介绍 Python 接口并探索常用包。
查看详情Right Arrow
开始课程
查看更多Right Arrow