3

我对以下行为感到惊讶:

>>> a=['a','b','c','d','e','f','g']
>>> en=enumerate(a)
>>> list(en)
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]
>>> list(en)
[]
>>> # en changed?   let's try that again!
>>> a=['a','b','c','d','e','f','g']
>>> en=enumerate(a)
>>> tuple(en)
((0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'))
>>> tuple(en)
()
>>> # en changes again?

我假设这list()只会从 en 中的数据构建一个列表,并且不会以任何方式更改它。与 相同tuple()。但它们都以“深刻”的方式影响 en。我是误解了什么list()tuple()还是我误解了enumerate()?谢谢。

4

4 回答 4

6

我认为您误解了 enumerate()。

>>> en=enumerate(a)

是生成器/迭代器,而不是数据结构。一旦你通过'en'运行一次,通过创建列表,生成器已经运行并且什么都没有了。再次尝试 list(en) 是尝试遍历已到达其末尾的迭代器,因此那里什么也没有。

于 2013-04-24T23:48:46.533 回答
5

enumerate返回一个迭代器,而不是像列表这样的可迭代对象。这意味着listandtuple只能enumerate通过重复调用其next()方法直到迭代器耗尽,才能获取 ' 的返回值的所有元素,之后迭代器和 Python 中的所有其他迭代器一样,将无法再产生任何元素。

于 2013-04-24T23:47:53.830 回答
3

list和也没有什么特别之处tuple。无论您如何消费en,这都会发生,包括通过您自己的手写for循环:

>>> a=['a','b','c','d','e','f','g']
>>> en=enumerate(a)
>>> en
<enumerate object at 0x21172d0>
>>> for index, elem in en:
...   print index, elem
... 
0 a
1 b
2 c
3 d
4 e
5 f
6 g
>>> for index, elem in en:
...   print index, elem
... 
>>> 

请注意,这en是一个“枚举对象”,而不是列表或元组,并且打印它并没有尝试打印其内容。这是因为enumerate实际上并没有生成包含所有相同数据a以及索引值的数据结构。相反,它返回一个小对象,该对象在内部记住它正在迭代的容器、它到达的位置以及它达到的计数。这就是生成“下一个”值所需的全部内容,因此即使它不是容器本身也可以对其进行迭代。

这样做的原因是人们几乎从不存储 的结果enumerate,通常会调用它以立即使用循环对其进行迭代for。为此,花时间和内存来构建所有数据的副本并一次将所有索引保存在内存中是浪费时间和内存的。随时生产它们就足够了。

如果您确实需要存储生成的数据enumerate以多次使用(或在生成它的地方以外的其他地方使用),那么您将需要该副本。最简单的方法实际上是做类似en = list(enumerate(a)). 然后您可以en完全按照您的预期使用。

于 2013-04-25T00:01:56.573 回答
2

您可能不完全理解enumerate()(或者,我可能误解了这个问题)。查看help(enumerate)文档(特别是关于产生 索引的部分:

Help on class enumerate in module __builtin__:

class enumerate(object)
 |  enumerate(iterable[, start]) -> iterator for index, value of iterable
 |
 |  Return an enumerate object.  iterable must be another object that supports
 |  iteration.  The enumerate object yields pairs containing a count (from
 |  start, which defaults to zero) and a value yielded by the iterable argument.
 |  enumerate is useful for obtaining an indexed list:
 |      (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
 |
 |  Methods defined here:
 |
 |  __getattribute__(...)
 |      x.__getattribute__('name') <==> x.name
 |
 |  __iter__(...)
 |      x.__iter__() <==> iter(x)
 |
 |  next(...)
 |      x.next() -> the next value, or raise StopIteration
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __new__ = <built-in method __new__ of type object>
 |      T.__new__(S, ...) -> a new object with type S, a subtype of T
于 2013-04-24T23:47:52.503 回答