9

I've recently made the following example for Pythons for ... else:

def isPrime(element):
    """ just a helper function! don't get religious about it! """
    if element == 2:
        return True
    elif element <= 1 or element % 2 == 0:
        return False
    else:
        for i in xrange(3, element, 2):
            print i
            if element % i == 0:
                return False
    return True


myList = [4, 4, 9, 12]

for element in myList:
    if isPrime(element):
        break
else:
    print("The list did not contain a prime.")

A fellow student told me, that this task can be done with Scala like this:

List(4, 4, 9, 12) exists isPrime

Which gets lazy evaluated.

Does something similar like the exists-keyword exist in Python? Or is there a PEP for that?

2
  • 3
    You probably want to check that element == 2 before element % 2 == 0; the latter is always true when the former is true. Commented Jun 9, 2012 at 6:25
  • Thanks, I've corrected it. But that is only an example to make a scenario where it could be used. Commented Jun 9, 2012 at 6:40

2 Answers 2

24
myList = [4, 4, 9, 12]

if not any(isPrime(x) for x in myList):
    print("The list did not contain a prime")

Python also has all() which cranks through any sequence and returns True if all elements evaluate true.

any() and all() both have short-circuit evaluation: if any() finds any element that evaluates true, it stops and returns True; and if all() finds any element that evaluates false, it stops and returns False.

Both are "lazy" in that they use Python iteration to pull values one at a time. For example:

import random
def rand_sequence(n_max):
    while True:
        next_random = random.randint(0, n_max)
        print(next_random)
        yield next_random

all(isPrime(x) for x in rand_sequence(20))

This will iterate until a non-prime number is found, then return False. It prints the numbers as a side-effect so you can watch it work. I just tried this and got:

17
3
0

P.S. I went to a talk at a Python conference, and the speaker mentioned that he commonly uses any() as a very efficient way to do a loop. A for loop re-binds the loop variable for each loop, but any() doesn't do that; it just keeps checking values. So if you use any() with a function that always returns None or a false value, it will iterate its way all to the end of the sequence, and according to that guy, it's the fastest way in Python to do it. (And if your function returns a value that is not None and isn't false, you can use all() for the same trick. The only time it doesn't work is if sometimes the function returns a true value and sometimes it returns a false value. But you can force it to always work:

any(my_function(x) and False for x in sequence)

P.P.S. Let's use all() to rewrite isPrime()! I'll change the name to is_prime() to conform to PEP 8. http://www.python.org/dev/peps/pep-0008/

def is_prime(element):
    """ just a helper function! don't get religious about it! """
    if element == 2:
        return True
    elif element <= 1 or element % 2 == 0:
        return False
    else:
        return all(element % i for i in xrange(3, element, 2))
Sign up to request clarification or add additional context in comments.

4 Comments

I didn't realize any and all short-circuited! Great.
Yes, the short-circuit behavior is the big advantage over using reduce() with a logical AND or logical OR operator.
Note that while both short-circuit, the laziness in the expression is provided by using a generator expression.
Well, if the Python developers were really stupid, any() and all() could call list() on the iterator, and then it wouldn't be lazy anymore. Using the Python iterator interface makes a function lazy, IMHO. (If the Python developers were that stupid, my rand_sequence() example would blow up because that generator will run forever if you let it; note the while True: loop.) Of course some functions can't be lazy; sorted() comes to mind. Try x = sorted(rand_sequence(20)) and watch the side-effect print numbers fly. You don't even need to evaluate the iterator.
-1
[x for x in myList if isPrime(x)]

2 Comments

This just a list comprehension, not short-circuit behavior
Code-only answers usually don't explain anything. I'd recommend adding an explanation in the near future, so this post doesn't get downvoted more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.