Python xrange作为迭代器和分块

Python xrange作为迭代器和分块,python,range,xrange,Python,Range,Xrange,片段 xi = xrange(10) zip(xi,xi) 及 表现不同。我希望能得到 [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)] 在第一个代码段中也是如此,但它返回 [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)] 相反。隐式容器似乎正在被静默复制。有人能解释一下这是怎么回事吗?以及选择这种语义背后的推理 >>>

片段

 xi = xrange(10)
 zip(xi,xi)

表现不同。我希望能得到

  [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
在第一个代码段中也是如此,但它返回

[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)]

相反。隐式容器似乎正在被静默复制。有人能解释一下这是怎么回事吗?以及选择这种语义背后的推理

>>> sys.version
'2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)]'

xrange对象已经不是迭代器,而是一个iterable对象。通过将迭代器馈送到
iter
函数,可以获得迭代器。
zip
函数对其所有参数隐式调用
iter
,因此它在xrange对象上生成两个并行迭代器。在第二个示例中,您手动调用一次iter,因此您将苹果与橙子进行比较。要使
xrange
也达到您想要的效果,您应该

In [5]: it = iter(xrange(10))
   ...: zip(it, it)
Out[5]: [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

xrange不是任何类型的迭代器。人们一直称它为发电机,但它不是;xrange是一个不可变的序列,就像元组一样:

>>> x = xrange(5)
>>> x[2]
2
>>> for i in x:
...     print i
...
0
1
2
3
4
>>> for i in x:
...     print i
...
0
1
2
3
4

与任何其他序列类型一样,每次从xrange请求迭代器时,都会得到一个新的独立迭代器。因此,当你自己压缩
xrange(10)
时,你会得到与自己压缩
[0,1,2,3,4,5,6,7,8,9]
相同的输出,而不是压缩
iter([0,1,2,3,4,5,6,7,8,9])
时的输出。

我认为你对类型的理解有点欠缺。基于pythons关于
xrange
类型的文档:

xrange类型是一个不可变的序列,通常用于循环。xrange类型的优点是,xrange对象将始终占用相同的内存量,无论它所代表的范围大小如何。没有一致的性能优势

以及以下重要部分:

XRange对象的行为很少:它们只支持索引、迭代和len()函数

xrange
对象不是迭代器,它只是一个不透明的序列类型,它生成与相应列表相同的值,而实际上没有同时存储它们,因为不遍历迭代器前面的项就无法访问迭代器元素,并且它不支持索引或
len()之类的操作
function。当您遍历迭代器时,您无法返回


因此,在第二个代码中,
zip
函数在每次迭代中使用每个项目,并且它可以访问下一个项目。

“似乎隐式容器正在被静默复制。”-你是什么意思?为什么需要复制才能产生观察到的行为?您希望从
xi=[1,2,3,4]中得到什么;zip(xi,xi)
?(此外,尽管人们一再称它为生成器,但xrange不是生成器。xrange是一个不变的序列。)@user2357112您的第二条评论解释了这一点。我期望xrange作为生成器是“有状态的”,而不是一成不变的。我一直认为xrange具有与生成器相同的语义。很高兴被纠正。@srean实际上它大约90%类似于
范围
,但例如,对于迭代器,我们可以说它10%类似于范围:)(仅举个例子)
>>> x = xrange(5)
>>> x[2]
2
>>> for i in x:
...     print i
...
0
1
2
3
4
>>> for i in x:
...     print i
...
0
1
2
3
4