简体   繁体   English

python itertools:使用islice循环

[英]python itertools: Using cycle with islice

Question: 题:

I have the code below. 我有下面的代码。 I want to know why does it not matter whether or not I include the line with the comment in the code below. 我想知道为什么我是否在下面的代码中包含注释行。

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

Output: 输出:

1
4
5
2
6
3

Also checkout roundrobin recipe at 还要检查roundrobin食谱

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

This code shows that islice is impacting cc 此代码显示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)) 

Output 产量

<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

Short course: the behaviors with and without rebinding cc aren't generally the same, but the outputs happen to be the same for the specific input you used. 短期课程:有和没有重新绑定cc的行为通常不相同,但输出恰好与您使用的特定输入相同。

Long course: let's call your three iterators A, B and C. 长期课程:让我们打电话给你的三个迭代器A,B和C.

Without the cc rebinding: A produces 1, B produces 4, C produces 5, A produces 2, B raises StopIteration . 没有cc重新绑定:A产生1,B产生4,C产生5,A产生2,B产生StopIteration p drops to 2. Then C produces 6, A produces 3, and B raises StopIteration again . p下降到2.然后C产生6,A产生3,B 再次引发StopIteration p drops to 1. C raises StopIteration . p降至StopIteration引发StopIteration p drops to 0, and the loop exits. p下降到0,循环退出。

With the cc rebinding: A produces 1, B produces 4, C produces 5, A produces 2, B raises StopIteration . 使用cc重新绑定:A产生1,B产生4,C产生5,A产生2,B产生StopIteration p drops to 2. All the same so far. p下降到2.到目前为止一切都一样。 The purpose of the rebinding in the round-robin algorithm is to remove exhausted iterators. 循环算法中重新绑定的目的是删除耗尽的迭代器。 It so happens that in this specific example it makes no difference to the outcome. 碰巧在这个具体的例子中,它对结果没有影响。 With the rebinding islice(cc, 2) takes "the next two things" from cc , which are, in order, C and A. B is no longer there. 使用重新绑定islice(cc, 2)cc获取“接下来的两件事”,按顺序,C和A. B不再存在。 Then C and A are put in a new cycle . 然后C和A进入一个新的cycle

Then C produces 6, A produces 3, and C raises StopIteration . 然后C产生6,A产生3,C产生StopIteration p drops to 1. The cc rebinding gets rid of C (the exhausted iterator), leaving just A in a new cycle . p降到1. cc重新绑定摆脱了C(耗尽的迭代器),在新的cycle只留下了A. The loop goes around, and A raises StopIteration . 循环StopIteration ,A引发StopIteration p drops to 0, and we're done. p降到0,我们就完成了。

Of course removing exhausted iterators is crucial to making round-robin work correctly in general. 当然,删除耗尽的迭代器对于使循环正常工作至关重要。 But, as you've shown, there are specific cases in which that doesn't matter :-) 但是,如您所示,有些具体情况无关紧要:-)

Simple example 简单的例子

A simple case where rebinding cc makes a huge difference: 重新绑定cc一个简单案例有很大的不同:

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

With rebinding, we get all 5 values. 通过重新绑定,我们获得所有5个值。 Without rebinding, we only get 1 and 2. 没有重新绑定,我们只得到1和2。

well... it looks like it's doing what is expected here. 嗯......看起来它正在做这里所期待的事情。

So, normally, cycle works like this: 所以,通常,循环的工作方式如下:

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

It's going to store off values until it gets a StopIterator, and then it's going to start returning values from its saved list. 它将存储值,直到它获得StopIterator,然后它将开始从其保存的列表返回值。 In this case, that's going to be [iter(a), iter(b), iter(c)] (where iter(x) is a listiterator object itself, across whatever is inside). 在这种情况下,那将是[iter(a), iter(b), iter(c)] (其中iter(x)是一个listiterator对象本身,跨越任何内部)。 So chain is actually returning something like this: 因此,链实际上会返回这样的东西:

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

What looks looks like when you run it: 运行它时看起来像什么:

[1, 4, 5, 2, StopIterator]

But that's the value of k.next(), not k. 但这是k.next()的值,而不是k。 the cc itself is not returning the StopIterator, the object it returns is. cc本身没有返回StopIterator,它返回的对象是。

Now, you call islice(cc,2) . 现在,你打电话给islice(cc,2) This should return the sequence [iter(c), iter(a)] , as those are the next two items in the sequence. 这应该返回序列[iter(c), iter(a)] ,因为它们是序列中的下两个项目。 Again, you want cc to cycle them, but now you should get 再一次,你想让cc循环它们,但现在你应该得到它

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

You won't notice much of a difference yet, but that's because your slice is less than the length of the original. 你不会注意到很多差异,但那是因为你的切片小于原始切片的长度。 In other words, the original would have gone [iter(c), iter(a), iter(b), iter(c), iter(a), ...] 换句话说,原件会消失[iter(c),iter(a),iter(b),iter(c),iter(a),...]

but you have to go farther than two items to see that difference, and... 但你必须走得比两个项目更远才能看到这种差异,并......

You start pulling items off and you get 你开始拉掉物品就可以了

[6, 3, StopIterator]

Only two items, so they are the same two items you'd get without the islice. 只有两个项目,所以它们是你在没有islice的情况下得到的两个项目。

Now, when you do the islice(cc, 2) , you get the next two items which are [iter(a), iter(c)] . 现在,当您执行islice(cc, 2) ,您将获得接下来的两个项目[iter(a), iter(c)] Both of these are exhausted, so you get 这两个都用尽了,所以你得到了

[StopIterator]

and your exact sequence. 和你的确切顺序。

I don't know what you are expecting, but this works exactly as i would expect it to. 我不知道你在期待什么,但这完全符合我的预期。

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

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