Blm33
Blm33

Reputation: 27

How to write more Pythonic Code

I started learning python today from the tutorial on the official site.

When reading about filter(function, sequence) i thought of making a function that returns if a number is prime to use it with the filter.

notDividedBy = [2,3,4,5,6,7,8,9]

def prime(num):
    """True if num is prime, false otherwise"""    
    copy = notDividedBy[:]
    check = True
    if num in copy:
        copy.remove(num)
    for x in copy:
        if num % x == 0:
            check = False
            break
    return check

The above code works in the shell.

My question is: Since i feel like although a solution, it is not the most elegant one, can anyone transform this code to something more python-like?(better structure? less lines?)

I believe it would help me for better understanding of the basics of the language.

The thing is, don't use any imports or anything, just simple staff.

Upvotes: 1

Views: 618

Answers (4)

Erik Lunna
Erik Lunna

Reputation: 110

Here's a 2 liner using filter().

def prime(num):
    """True if num is prime, false otherwise"""
    if num < 2:
        return False
    return len(filter(lambda x: num % x == 0, range(2, num))) == 0

Upvotes: 0

mgilson
mgilson

Reputation: 310099

How about this one:

def is_prime(num):
    return not any(num%i == 0 for i in xrange(2,num/2+1))

for i in xrange(10):
    print i, is_prime(i)

Explanation

start with:

(num%i==0 for i in xrange(2,num/2+1))

This is a generator expression. I could have made it a list comprehension:

[num%i==0 for i in xrange(2,num/2+1)]

The list comprehension is equivalent to:

ll=[]
for i in xrange(2,num/2+1):
    ll.append(num%i==0)

The difference between the generator and the list comprehension is that the generator only gives up it's elements as you iterate over it -- whereas the list comprehension calculates all the values up front. Anyway, from the above code, you can see that the expression generates a sequence of True's and False's. True if the number can be divided by i and False otherwise. If we generate a sequence of all False numbers, we know we have a prime.

The next trick is the any built in function. It basically searches through an iterable and checks if any of the values is True. As soon as it hits a True, it returns True. If it gets to the end of the iterable, it returns False. So, if the entire sequence is False (a prime number) then any will return False, otherwise it returns True. This would be perfect for a not_prime function, but our function is is_prime, so we just need to invert that result using the not operator.

The benefit of using the generator expression is that it is nice and concise, but also that it allows any to return before checking every value which means that as soon as it finds a number that divides num, it returns instead of generating all num/2 numbers.

Anyway, I hope this explanation is helpful. If not, feel free to leave a comment and I'll try to explain better.

Upvotes: 4

dfb
dfb

Reputation: 13289

One thing off the bat, if you are going to implement prime testing in this fashion, there's no reason to use an auxillary array

def prime(num):
    """True if num is prime, false otherwise"""    
    check = True
    #if num in copy:
    #    copy.remove(num)
    for x in range(2,x-1):
        if num % x == 0:
            check = False
            break
    return check

Upvotes: 0

Joel Cornett
Joel Cornett

Reputation: 24788

Creating many many copies of lists is not a particularly efficient way of doing things. Instead use the xrange() (Python 2.x) or range() (Python 3) iterator. Here's one (naive) way you could implement a primality test:

from math import sqrt

def isPrime(n):
    if n < 2: return False
    if n == 2: return True
    if not n % 2: return False #test if n is even

    #we've already remove all the even numbers, no need to test for 2
    #we only need to test up to sqrt(n), because any composite numbers can be
    #   factored into 2 values, at least one of which is < sqrt(n)
    for i in xrange(3, int(sqrt(n)) + 1, 2): 
        if not n % i:
            return False
    return True

Upvotes: 4

Related Questions