python itertools:使用islice循环

时间:2013-10-02 18:40:02

标签: python itertools

问题:

我有以下代码。我想知道为什么我是否在下面的代码中包含评论这一行并不重要。

#!/usr/bin/env python

from itertools import *
import time
cc = cycle([ iter([1,2,3]), iter([4]) , iter([5,6]) ] )
p = 3
while p:
    try:
        for k in cc:
            print k.next()
    except StopIteration:
        p = p - 1
        cc = cycle(islice(cc,  p))  # this does not matter

输出:

1
4
5
2
6
3

还可以在

结帐roundrobin食谱

http://docs.python.org/2.7/library/itertools.html

此代码显示islice正在影响cc

#!/usr/bin/env python

from itertools import *
import time
cc = cycle([ iter([1,2,3]), iter([4]) , iter([5,6]) ] )
p = 3
while p:
    try:
        for k in cc:
            print k,k.next()
    except StopIteration:
            print "stop iter"
            p = p - 1
            cc = cycle(islice(cc,  p)) 

输出

<listiterator object at 0x7f32bc50cfd0> 1
<listiterator object at 0x7f32bc518050> 4
<listiterator object at 0x7f32bc518090> 5
<listiterator object at 0x7f32bc50cfd0> 2
<listiterator object at 0x7f32bc518050> stop iter
<listiterator object at 0x7f32bc518090> 6
<listiterator object at 0x7f32bc50cfd0> 3
<listiterator object at 0x7f32bc518090> stop iter
<listiterator object at 0x7f32bc50cfd0> stop iter

2 个答案:

答案 0 :(得分:4)

短期课程:有和没有重新绑定cc的行为通常相同,但输出发生对于特定输入是相同的你用过。

长课程:让我们调用你的三个迭代器A,B和C.

没有cc重新绑定:A产生1,B产生4,C产生5,A产生2,B产生StopIterationp降至2.然后C产生6,A产生3,B再次提升StopIteration p降至1. C引发StopIterationp降为0,循环退出。

使用cc重新绑定:A生成1,B生成4,C生成5,A生成2,B生成StopIterationp下降到2.到目前为止一切都是如此。循环算法中重新绑定的目的是删除耗尽的迭代器。碰巧在这个具体的例子中,它对结果没有影响。使用重新绑定islice(cc, 2)cc获取“接下来的两件事”,按顺序,C和A. B不再存在。然后将C和A放入新的cycle

然后C产生6,A产生3,C产生StopIterationp降为1. cc重新绑定取消C(耗尽的迭代器),只留下新的cycle中的A.循环绕过,A引发StopIterationp降至0,我们已经完成了。

当然,删除耗尽的迭代器对于使循环正常工作至关重要。但是,如您所示,有些具体情况无关紧要: - )

简单示例

重新绑定cc的一个简单案例有很大的不同:

cc = cycle([iter([1,2,3,4,5]), iter([])])
p = 2

通过重新绑定,我们获得了所有5个值。没有重新绑定,我们只得到1和2。

答案 1 :(得分:3)

好吧......看起来它正在做这里所期待的事情。

所以,通常,循环的工作原理如下:

cycle([1,2,3,4,5]) -> [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]

它将存储值,直到它获得StopIterator,然后它将开始从其保存的列表中返回值。在这种情况下,那将是[iter(a), iter(b), iter(c)](其中iter(x)是一个listiterator对象本身,不管是什么内部)。因此,链实际上会返回这样的东西:

[iter(a), iter(b), iter(c), iter(a), iter(b), iter(c), iter(a), iter(b), iter(c), ...]

运行时看起来很像:

[1, 4, 5, 2, StopIterator]

但这是k.next()的值,而不是k。 cc本身没有返回StopIterator,它返回的对象是。

现在,您致电islice(cc,2)。这应该返回序列[iter(c), iter(a)],因为它们是序列中的下两个项目。再一次,你想让cc循环它们,但现在你应该得到

[iter(c), iter(a), iter(c), iter(a), iter(c), iter(a), ...]

你不会发现太多差异,但那是因为你的切片小于原始切片的长度。换句话说,原件就会消失     [iter(c),iter(a),iter(b),iter(c),iter(a),...]

但你必须走得比两个项目更远才能看到这种差异,并且......

你开始拉动物品然后你就

[6, 3, StopIterator]

只有两个项目,因此它们与没有islice的情况相同。

现在,当您执行islice(cc, 2)时,您将获得接下来的两个[iter(a), iter(c)]项。这两个都用尽了,所以你得到了

[StopIterator]

和你的确切顺序。

我不知道你在期待什么,但这完全符合我的预期。