4

问题:

我有下面的代码。我想知道为什么我是否在下面的代码中包含带有注释的行并不重要。

#!/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
4

2 回答 2

4

嗯......看起来它正在做这里预期的事情。

所以,通常,循环是这样工作的:

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]

和你的确切顺序。

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

于 2013-10-02T20:11:49.523 回答
4

短期课程:有和没有重新绑定的行为cc通常不同的,但是对于您使用的特定输入,输出恰好是相同的。

长课程:让我们将您的三个迭代器称为 A、B 和 C。

没有cc重新绑定:A 产生 1,B 产生 4,C 产生 5,A 产生 2,B raises StopIterationp下降到 2。然后 C 产生 6,A 产生 3,BStopIteration 再次加注。 p下降到 1。C 加注StopIterationp降为 0,循环退出。

重新cc绑定:A 产生 1,B 产生 4,C 产生 5,A 产生 2,B raises StopIterationp下降到 2。到目前为止都一样。循环算法中重新绑定的目的是删除耗尽的迭代器。碰巧的是,在这个特定的例子中,它对结果没有影响。随着重新绑定islice(cc, 2)从 中获取“接下来的两件事” cc,它们依次是 C 和 A。B 不再存在。然后将 C 和 A 放入一个新的cycle.

然后 C 产生 6, A 产生 3, C raise StopIterationp下降到 1。cc重新绑定摆脱了 C (耗尽的迭代器),只留下 A 在 newcycle中。循环循环,A 加注StopIterationp降到0,我们就完成了。

当然,删除耗尽的迭代器对于使循环正常工作通常是至关重要的。但是,正如您所展示的,在某些特定情况下这并不重要:-)

简单的例子

cc重新绑定产生巨大差异的简单案例:

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

通过重新绑定,我们得到所有 5 个值。如果不重新绑定,我们只会得到 1 和 2。

于 2013-10-02T20:19:51.767 回答