2

片段

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

 xi = iter(range(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)]'
4

3 回答 3

1

xrange 对象还不是一个迭代器,而是一个可迭代对象。您可以通过将迭代器提供给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)]
于 2015-06-26T07:55:38.643 回答
1

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])使用自身进行压缩。

于 2015-06-26T08:04:25.473 回答
1

我认为您对xrange类型有误解。基于关于xrange类型的pythons文档:

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

以及以下重要部分:

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

xrange对象不是迭代器,它只是一个不透明的序列类型,它产生与相应列表相同的值,但实际上并没有同时存储它们,因为如果不遍历其前面的项目就无法访问迭代器元素并且它不支持操作像索引或len()函数。当你遍历迭代器时,你不能回去!

所以在第二个代码中,zip函数在每次迭代中消耗每个项目,它只能访问下一个项目。

于 2015-06-26T08:20:08.950 回答