Python中的enumerate是惰性的吗?

117 投票
4 回答
49262 浏览
提问于 2025-04-16 02:14

我想知道当我把一个生成器函数的结果传给Python的enumerate()时,会发生什么。比如:

def veryBigHello():
    i = 0
    while i < 10000000:
        i += 1
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word
    

这个enumerate是懒惰地迭代,还是会先把所有东西都装进<enumerate object>里?我99.999%确定是懒惰的,所以我可以像对待生成器函数一样对待它吗,还是说我需要注意什么?

4 个回答

15

因为你可以在不出现内存溢出错误的情况下调用这个函数,所以它肯定是懒惰的。

def veryBigHello():
    i = 0
    while i < 1000000000000000000000000000:
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word
56

其实比之前的建议还要简单:

$ python
Python 2.5.5 (r255:77872, Mar 15 2010, 00:43:13)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> abc = (letter for letter in 'abc')
>>> abc
<generator object at 0x7ff29d8c>
>>> numbered = enumerate(abc)
>>> numbered
<enumerate object at 0x7ff29e2c>

如果 enumerate 不是懒惰求值的话,它会返回 [(0,'a'), (1,'b'), (2,'c')] 或者一些(几乎)相同的结果。

当然,enumerate 实际上只是一个很酷的生成器:

def myenumerate(iterable):
   count = 0
   for _ in iterable:
      yield (count, _)
      count += 1

for i, val in myenumerate((letter for letter in 'abc')):
    print i, val
132

这很懒惰。其实很容易证明这一点:

>>> def abc():
...     letters = ['a','b','c']
...     for letter in letters:
...         print letter
...         yield letter
...
>>> numbered = enumerate(abc())
>>> for i, word in numbered:
...     print i, word
...
a
0 a
b
1 b
c
2 c

撰写回答