[Tutor] List comprehension question

Richard D. Moores rdmoores at gmail.com
Mon Nov 8 01:16:36 CET 2010


On Sun, Nov 7, 2010 at 15:53, Hugo Arts <hugo.yoshi at gmail.com> wrote:
> On Mon, Nov 8, 2010 at 12:36 AM, Richard D. Moores <rdmoores at gmail.com> wrote:
>> def proper_divisors(n):
>>     """
>>     Return the sum of the proper divisors of positive integer n
>>     """
>>     return sum([x for x in range(1,n) if int(n/x) == n/x])
>>
>> The list comprehension is this function is inefficient in that it computes
>> n/x twice. I'd like to do an  a = n/x and use a in
>> "if int(a) == a", but I don't know how.
>>
>
> You can't do that inside a list comprehension. Either get rid of the
> comprehension and do a regular loop, or get rid of the n/x expression.
>
> I'd suggest replacing the whole check with x % n == 0.

Wow! using n % x == 0 is about 3x faster than what I had before.

> n is a proper
> divisor of x if there is no remainder after division, after all. This
> also means you won't have to do a cast, which tend to be fairly
> expensive.

I don't know what a cast is. Would that be the int(n/x)?

Here are 2 versions, of about equal speed:

def proper_divisors(n):
    """
    Return the sum of the proper divisors of positive integer n
    """
    return sum([x for x in range(1,n) if n % x == 0])

def proper_divisors(n):
    sum_ = 0
    for x in range(1,n):
        if n % x == 0:
            sum_ += x
    return sum_

> On another note, getting rid of the list comprehension and using a
> generator expression will be even faster, since you won't have to
> build the list.

Could you spell that out for me?

Thanks,

Dick


More information about the Tutor mailing list