[Tutor] List comprehension question

Steven D'Aprano steve at pearwood.info
Mon Nov 8 22:41:34 CET 2010


Alan Gauld wrote:
> 
> "Steven D'Aprano" <steve at pearwood.info> wrote
> 
>> I'm going to be pedantic here... but to quote the Middleman, 
>> specificity is the soul of all good communication.
> 
> Be pedantic! :-)
> I really liked the explanation although I already sort of knew most of it.
> But there were a few nuggets in there I'd missed, like range() being
> a type all of its own.

Thank you :)

> But one, slightly off-topic, question:
> 
>> def proper_divisors(n):
>>     return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)
>>
> 
> Why use math.sqrt() instead of just using the ** operator?
> 
>     return sum(x for x in range(1, int(n**0.5)) if n%x == 0)
> 
> I'd have expected ** to be significantly faster than calling the
> function, and given this is a performance tweak...?


Mostly personal taste, but I would expect math.sqrt() to be more 
accurate than a generic exponentiation operator, although in this case 
the difference shouldn't matter. If your value for n is so large that 
you need to care about the floating point rounding errors in n**0.5, 
you're probably using the wrong tool.

As for the speed, sqrt() only gets called once, so the difference 
shouldn't matter. But for what it's worth:

[steve at sylar ~]$ python3 -m timeit -s "import math" "math.sqrt(1234567)"
1000000 loops, best of 3: 0.486 usec per loop
[steve at sylar ~]$ python3 -m timeit "1234567**0.5"
1000000 loops, best of 3: 0.265 usec per loop

So on my machine, the overhead of calling a function is about 0.2 
micro-seconds. Compare that to:

[steve at sylar ~]$ python3 -m timeit -s "n=1234567" "sum(x for x in 
range(1, int(n**0.5)) if n%x == 0)"
1000 loops, best of 3: 515 usec per loop


So changing from math.sqrt(n) to n**0.5 increases the overall speed by 
approximately 0.04%. Truly a micro-optimization :)


(I'm deliberately not including the time to import math here. I assume 
that the function proper_divisors() will be in a module with other maths 
related functions, and therefore you need to import it regardless.)



-- 
Steven



More information about the Tutor mailing list