为什么list和tuple会改变枚举的输出?

时间:2013-04-24 23:42:10

标签: python list tuples enumerate

我对以下行为感到惊讶:

>>> 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()相同。但他们都以“深刻”的方式影响恩。我是否误解了list()tuple()的某些内容,或者我误解了enumerate()?感谢。

4 个答案:

答案 0 :(得分:6)

我认为你误解了枚举()。

>>> en=enumerate(a)

是生成器/迭代器,而不是数据结构。一旦你运行'en'一次,通过创建列表,生成器已经运行,没有任何东西。再次尝试list(en)试图迭代已经到达它的迭代器,所以那里什么都没有。

答案 1 :(得分:5)

enumerate会返回iterator,而非iterable列表。这意味着listtuple只能通过反复调用其enumerate方法获取next()的所有元素的返回值,直到迭代器耗尽为止,之后与Python中的所有其他迭代器一样,iterator将无法再生成任何元素。

答案 2 :(得分:3)

listtuple也没什么特别之处。如果您使用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

答案 3 :(得分: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