The return value of the nosklo chunker
function is called a generator, an object that will generate values when being iterated. In this case the generator is created using a generator expression, an indivisible piece of code between the parentheses: (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
.
>>> def chunker(seq, size):
... return (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
...
>>> result = chunker([1, 2, 3], 2)
>>> print(result)
<generator object <genexpr> at 0x10581e1e0>
>>> next(result)
[1, 2]
>>> next(result)
[3]
Regarding what gets called, we can rewrite the loop code like this to see it better:
>>> generator = chunker(animals, 3)
>>> for chunk in generator:
... print chunk
...
['cat', 'dog', 'rabbit']
['duck', 'bird', 'cow']
['gnu', 'fish']
The chunker
functions gets called only once and returns the generator object, which we store in the generator
variable. The for
loop then only works with this generator
object and calls it 3 times.
To be able to print the actual calls of this generator, you would have to include the print
statement inside the generator expression (seq[pos:pos + size] for pos in xrange(0, len(seq), size))
, which is not allowed. But we can rewrite this generator expression to a normal generator function using the yield
statement, a more verbose but also more versatile form of generator where we can include the print
statement and which will work as you expected initially:
>>> def chunker2(seq, size):
... for pos in xrange(0, len(seq), size):
... print('chunker2 generator called')
... yield seq[pos:pos + size]
...
>>> for group in chunker2(animals, 3):
... print group
...
chunker2 generator called
['cat', 'dog', 'rabbit']
chunker2 generator called
['duck', 'bird', 'cow']
chunker2 generator called
['gnu', 'fish']
Here the chunker2
function itself is the actual generator and gets called 3 times.