Performing any ()

This is basically an exercise to learn Python. I wrote this function to check if a number is prime:

def p1(n): for d in xrange(2, int(math.sqrt(n)) + 1): if n % d == 0: return False return True 

Then I realized that I could easily rewrite it with any ():

 def p2(n): return not any((n % d == 0) for d in xrange(2, int(math.sqrt(n)) + 1)) 

I expected p2 to be faster than, or at least as fast as p1, because any () is built-in, but for a large number of isp p2 is slightly slower:

 $ python -m timeit -n 100000 -s "import test" "test.p1(999983)" 100000 loops, best of 3: 60.2 usec per loop $ python -m timeit -n 100000 -s "import test" "test.p2(999983)" 100000 loops, best of 3: 88.1 usec per loop 

Am I using any () here incorrectly? Is there a way to write this function using any () so that it goes right through the iteration?

Update: Numbers for Even Simpler

 $ python -m timeit -n 1000 -s "import test" "test.p1(9999999999971)" 1000 loops, best of 3: 181 msec per loop $ python -m timeit -n 1000 -s "import test" "test.p2(9999999999971)" 1000 loops, best of 3: 261 msec per loop 
+6
source share
1 answer

The difference in performance is minimal, but the reason it exists is because any causes the generator expression to be built and an extra function call compared to the for loop. Both have the same behavior though (label rating).

As the size of your input grows, the difference will not decrease (I was mistaken), because you use a generator expression, and to iterate it, you need to call the method ( .next() ) on it and an additional stack frame. any does it under the hood, of course.

The for loop iterates over the xrange object. any iterates over the expression of the generator, which itself iterates over the xrange object.

In any case, use the one that produces the most readable / supported code. Choosing one over the other will have little effect if one has an effect on any program you write.

+4
source

Source: https://habr.com/ru/post/977248/


All Articles