Reputation: 31
I was trying to use functools.partial with itertools.count, by currying zip with itertools.count():
g = functools.partial(zip, itertools.count())
When calling g with inputs like "abc", "ABC", I noticed that itertools.count() mysteriously "jumps".
I thought I should get the same result as directly using zip with itertools.count()? like:
>>> x=itertools.count();
>>> list(zip("abc",x))
[('a', 0), ('b', 1), ('c', 2)]
>>> list(zip("ABC",x))
[('A', 3), ('B', 4), ('C', 5)]
But instead, I get the following -- notice the starting index at the second call of g is 4 instead of 3:
>>> g = functools.partial(zip, itertools.count())
>>> list(g("abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(g("ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]
Upvotes: 3
Views: 159
Reputation: 70602
Note that you'd get the same result if your original code used arguments in the same order as your altered code:
>>> x = itertools.count()
>>> list(zip(x, "abc"))
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> list(zip(x, "ABC"))
[(4, 'A'), (5, 'B'), (6, 'C')]
zip()
tries its first argument first, then its second, then its third ... and stops when one of them is exhausted.
In the spelling just above, after "abc"
is exhausted, it goes back to the first argument and gets 3
from x
. But its second argument is already exhausted, so zip()
stops, and the 3
is silently lost.
Then it moves on to the second zip()
, and starts by getting 4
from x
.
partial()
really has nothing to do with it.
Upvotes: 7
Reputation: 402553
It'll be easy to see why if you encapsulate itertools.count()
inside a function:
def count():
c = itertools.count()
while True:
v = next(c)
print('yielding', v)
yield v
g = functools.partial(zip, count())
list(g("abc"))
The output is
yielding 0
yielding 1
yielding 2
yielding 3
[(0, 'a'), (1, 'b'), (2, 'c')]
You'll see zip
will evaluate the next argument from count()
(so an extra value 3
is yielded) before it realises there isn't anything else left in the second iterable.
As an exercise, reverse the arguments and you'll see the evaluation is a little different.
Upvotes: 5