[ x for x in xrange(10) when p(x) ]

Bengt Richter bokr at oz.net
Sat Nov 12 03:07:08 CET 2005


On 10 Nov 2005 18:20:01 -0800, "bonono at gmail.com" <bonono at gmail.com> wrote:

>
>Bengt Richter wrote:
>> If you want to terminate a generator expression after the first sequence of elements
>> satisfying a condition, and you don't want to use takewhile, I don't know of a gotcha
>> to prevent you from just raising StopIteration, using an expression that will do that, e.g.,
>>
>>  >>> list (x for x in xrange(20) if x<5 or iter([]).next())
>>  [0, 1, 2, 3, 4]
>>
>> Or a bit more readably:
>>  >>> def stop(): raise StopIteration
>>  ...
>>  >>> list (x for x in xrange(20) if x<5 or stop())
>>  [0, 1, 2, 3, 4]
>>
>> IOW, your "when condition(x)" (IIUIC) can be spelled "if condition(x) or stop()"
>If it is a single loop, takewhile/dropwhile is perfectly fine but as I
>mentioned in another post, it is nested and the condition needs
>surrounding scope so seperate function and StopIteration doesn't work
>as it breaks out of the whole thing expression.
How do you mean? How did you write the expression?
E.g., there are two stop() calls in this one, but they are in different scopes:

 >>> list ((i,list(xseq)) for i, xseq in enumerate((x for x in xrange(20) if x<5 or stop()) for j
  in xrange(20) if j<4 or stop() ))
 [(0, [0, 1, 2, 3, 4]), (1, [0, 1, 2, 3, 4]), (2, [0, 1, 2, 3, 4]), (3, [0, 1, 2, 3, 4])]

Or, (perhaps) more prettily written (same syntax, just spread differently):

 >>> list(
 ...     (i,list(xseq)) for i, xseq in enumerate(
 ...         (x for x in xrange(20) if x<5 or stop())
 ...             for j  in xrange(20) if j<4 or stop()
 ...     )
 ... )
 [(0, [0, 1, 2, 3, 4]), (1, [0, 1, 2, 3, 4]), (2, [0, 1, 2, 3, 4]), (3, [0, 1, 2, 3, 4])]
 >>>

I would think takewile would do the same. Might as well see:

 >>> from itertools import takewhile
 >>> list(
 ...     (i,list(twiter)) for i, twiter in enumerate(
 ...         takewhile(lambda x:x<5, xrange(20))
 ...             for j in takewhile(lambda x:x<4, xrange(20))
 ...     )
 ... )
 [(0, [0, 1, 2, 3, 4]), (1, [0, 1, 2, 3, 4]), (2, [0, 1, 2, 3, 4]), (3, [0, 1, 2, 3, 4])]

Seems ok.

>
>takewhile/dropwhile still works in this case(because of the lambda
>which sees the surrounding scope).
>
Could you show your code with the traceback of its failure? I've lost context ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list