if does not evaluate

Peter Otten __peter__ at web.de
Fri Jun 11 12:55:04 EDT 2004


Jim Newton wrote:

> ah so i must encapsulate the predicate function in another named
> function which uses yield in order to have the iteration abort
> when the target item is reached?  can i simply put the predicate
> function inside a lambda?

You can always substitute a function identifier with a lambda, e. g

>>> x = ['Peter', 'Paul', 'Mary', 'Jane']
>>> True in itertools.imap(lambda o: o.startswith("M"), x)
True
>>>

Calling a "function containing a yield statement", aka a generator, returns
an iterator object, i. e. an object with a next() method, which, when
called, executes the generator until the next yield statement or raises a
StopIteration exception. All state is kept between invocations of next(). 

The actual shortcircuiting is done by the "in" operator. 

result = value in itertools.imap(predicate, sequence)

under the hood performs then

gen = itertools.imap(predicate, sequence)
try:
    while True:
        if value == gen.next():
            break # found a match, now go on with else: ...
except StopIteration: # no more items in sequence
    result = False
else:
    result = True

This may look complicated, but you can simplify it yourself, if you know
that the most common case

it = iter(sequence)
try:
    while True:
        item = it.next()
        # do something
except StopIteration:
    pass

is actually spelt out as

for item in sequence:
   # do something

So in the end we have just a fancy for loop in disguise:

for item in sequence: 
    if value == predicate(item):
       result = True
       break
else:
    result = False
         
which I see is how you solved the problem in the past...

Peter





More information about the Python-list mailing list