繁体   English   中英

为什么xrange能够在Python中重新开始?

[英]why is xrange able to go back to beginning in Python?

我从大多数pythonic方法中遇到了这个代码, 用于计算可迭代的匹配元素

r = xrange(1, 10)
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 3

r迭代一次。 然后它再次迭代。 我想如果一个迭代器被消耗掉,那么它就结束了,它不应该再次迭代。

生成器表达式只能迭代一次:

r = (7 * i for i in xrange(1, 10))
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 0

枚举(L):

r = enumerate(mylist)

和文件对象:

f = open(myfilename, 'r')

为什么xrange表现不同?

因为xrange不返回生成器。 它返回一个xrange对象

>>> type(xrange(10))
<type 'xrange'>

除了重复迭代之外, xrange对象还支持生成器不需要的其他东西 - 比如索引:

>>> xrange(10)[5]
5

他们也有一个长度:

>>> len(xrange(10))
10

他们可以逆转:

>>> list(reversed(xrange(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

简而言之, xrange对象实现了完整的序列 接口

>>> import collections
>>> isinstance(xrange(10), collections.Sequence)
True

他们只是在不占用大量内存的情况下完成它。

还要注意,在Python 3, range由返回的对象range具有完全相同的属性。

因为通过调用xrange()生成的xrange对象指定__iter__ ,每次迭代时都会提供自身的唯一版本(实际上是一个单独的rangeiterator对象)。

>>> x = xrange(3)
>>> type(x)
<type 'xrange'>
>>> i = x.__iter__()
>>> type(i)
<type 'rangeiterator'>

如果你所知道的是它是一个迭代器,那么一般来说你必须假设你只能迭代一次。 这并不意味着每个迭代器只能被消耗一次,只是每个迭代器至少可以消耗一次。 明显的例子是列表和其他序列支持此接口。

正如senderle和Amber所解释的那样,通过调用xrange获得的特定迭代器碰巧被实现,以便您可以多次迭代它们。

通用迭代器的想法允许迭代器在迭代后可能会耗尽。 这是因为许多迭代器(例如生成器,文件遍历等)难以实现,或者消耗更多内存或运行速度慢得多,如果它们必须支持任意多次遍历,并且通常这种功能甚至不会用过的。 因此,如果迭代器必须支持任意多次遍历,那么这些东西可能不会是迭代器。

长话短说,如果你正在编写上的任意未知的迭代器操作的代码,你认为它只能使用一次遍历,如果有人给你支持比你需要的功能更像一个对象也没关系。 如果您知道有关迭代器的一些其他信息(例如它也是一个序列,或者甚至是它是一个xrange对象),那么您可以编写代码以便在需要时使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM