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
http://docs.python.org/2.7/library/itertools.html
This code shows that islice
is impacting 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
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. 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). 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. the cc itself is not returning the StopIterator, the object it returns is.
Now, you call islice(cc,2)
. This should return the sequence [iter(c), iter(a)]
, as those are the next two items in the sequence. Again, you want cc to cycle them, but now you should get
[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), ...]
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.
Now, when you do the islice(cc, 2)
, you get the next two items which are [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.