Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"exists" keyword in Python?

Tags:

python

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?

like image 287
Martin Thoma Avatar asked Jun 09 '12 06:06

Martin Thoma


1 Answers

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))
like image 144
steveha Avatar answered Oct 05 '22 10:10

steveha