# when an iterable object is exhausted or not

MRAB python at mrabarnett.plus.com
Sat Aug 4 22:11:56 CEST 2012

On 04/08/2012 20:20, Franck Ditter wrote:
> Two similar iterable objects but with a different behavior :
>
> \$\$\$ i = range(2,5)
> \$\$\$ for x in i : print(x,end=' ')
>
> 2 3 4
> \$\$\$ for x in i : print(x,end=' ')        # i is not exhausted
>
> 2 3 4
>
> --------- Compare with :
>
> \$\$\$ i = filter(lambda c : c.isdigit(), 'a1b2c3')
> \$\$\$ for x in i : print(x,end=' ')
>
> 1 2 3
> \$\$\$ for x in i : print(x,end=' ')        # i is exhausted
>
> \$\$\$
>
> IMHO, this should not happen in Py3k.
> What is the rationale of this (bad ?) design, which forces the programmer
> to memorize which one is exhaustable and which one is not ?...
>
'range' returns a 'range' object:

>>> i = range(2,5)
>>> i
range(2, 5)

The 'for' loop passes it to 'iter' to get an iterator:

>>> iter(i)
<range_iterator object at 0x0135DB30>

More importantly:

>>> iter(i) is i
False

In other words, when asked for an iterator, the 'range' object always
creates a new one.

On the other hand, 'filter' returns a 'filter' object:

>>> i = filter(lambda c : c.isdigit(), 'a1b2c3')
>>> i
<filter object at 0x01360B30>

The 'for' loop passes it to 'iter' to get an iterator:

>>> iter(i)
<filter object at 0x01360B30>

More importantly:

>>> iter(i) is i
True

In other words, the 'filter' object returns _itself_ as the iterator.