delay and force in Python

Bengt Richter bokr at oz.net
Wed Jan 26 02:15:04 EST 2005

```On Tue, 25 Jan 2005 23:53:26 +1000, Nick Coghlan <ncoghlan at iinet.net.au> wrote:

>Peter Otten wrote:
>> Nick Coghlan wrote:
>>
>>
>>>>Py> print islice((x for x in xrange(1, 996) if x % 2 == 0), 1, 2).next()
>>>>4
>>>
>>>Wouldn't it be nice if this could be spelt:
>>>
>>>print (x for x in xrange(1, 996) if x % 2 == 0)[2]
>>>
>>>Well, I just put a patch on SF to enable exactly that:
>>>http://www.python.org/sf/1108272
>>
>>
>> I like it. Of course you always have to bear in mind that one giant leap for
>> a list could be _many_ small steps for an iterator.
>
>Indeed. The main cases I am thinking of involve picking off the first few items
>of an iterator (either to use them, or to throw them away before using the rest).
>
>And if an app actually *needs* random access, there's a reason lists still exist ;)
>
You can bail out of a generator expression with a raise-StopIteration expression spelled iter([]).next() ;-)

>>> def show(x): print x,; return x
...
>>> list(show(x) for x in xrange(20) if x<8 or iter([]).next())
0 1 2 3 4 5 6 7
[0, 1, 2, 3, 4, 5, 6, 7]

Well, since

>>> list(show(x) for x in xrange(20) if x<8)
0 1 2 3 4 5 6 7
[0, 1, 2, 3, 4, 5, 6, 7]

this change due to adding iter([]).next() might be more convincing:

>>> list(show(x) for x in xrange(20) if x<8 or True)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

>>> list(show(x) for x in xrange(20) if x<8 or iter([]).next() or True)
0 1 2 3 4 5 6 7
[0, 1, 2, 3, 4, 5, 6, 7]

Applied to example,

>>> print list(x for i,x in enumerate(x for x in xrange(1, 996) if x % 2 ==0) if i<3 or iter([]).next())[2]
6

or in case you just want one item as result,

>>> print list(x for i,x in enumerate(x for x in xrange(1, 996) if x % 2 ==0) if i==2 or i==3 and iter([]).next())[0]
6

Regards,
Bengt Richter

```