Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "not" faster than "bool()" in Python (or, speed of Python functions vs. statements)?

Tags:

python

I made an interesting observation the other day. I was experimenting with various ways to get the "truthiness" of an object and the speed of each, and I noticed that not is much faster than bool.

>>> bool([5, 6, 7])
True
>>> bool([])
False
>>> not not [5, 6, 7]
True
>>> not not []
False
>>> import timeit
>>> from numpy import mean
>>> mean(timeit.repeat('bool(a)', 'a = [5, 6, 7]', repeat=10))
0.19072036743164061
>>> mean(timeit.repeat('bool(a)', 'a = []', repeat=10))
0.18562331199645996
>>> mean(timeit.repeat('not not a', 'a = [5, 6, 7]', repeat=10))
0.072056698799133304
>>> mean(timeit.repeat('not not a', 'a = []', repeat=10))
0.073475956916809082
>>> mean(timeit.repeat('not a', 'a = [5, 6, 7]', repeat=10))
0.043941426277160647
>>> mean(timeit.repeat('not a', 'a = []', repeat=10))
0.044287109375000001

We can see that using the bool function is significantly slower than using the not statement, even though ultimately they do the same thing (return the boolean state of the object). Now, we have all been told that in Python the function overhead is large, but I was not expecting this type of discrepancy in this case for the following reasons:

  • bool() is a builtin function, meaning that it is written in C, and I would have expected this to have a rather low overhead
  • In both cases, Python has to assess the "truthiness" of the object internally (I would imagine they use the same C routines to do this internally)
    • In fact, not has to return the logical opposite of the object's "truthiness", so in theory it is doing a bit more work (but perhaps there is an implementation detail that gets around this)

In my mind, because both functions are doing essentially the same thing all the extra time must be coming from the function overhead. If that is the case, why is it that a statement is able to avoid so much overhead compared to a function? If it is not the overhead, why is bool() so much slower than not?


UPDATE: Here are also the min times in addition to the mean.

>>> min(timeit.repeat('bool(a)', 'a = [5, 6, 7]', repeat=10))
0.18180489540100098
>>> min(timeit.repeat('bool(a)', 'a = []', repeat=10))
0.1821761131286621
>>> min(timeit.repeat('not not a', 'a = [5, 6, 7]', repeat=10))
0.0707249641418457
>>> min(timeit.repeat('not not a', 'a = []', repeat=10))
0.07100605964660645
>>> min(timeit.repeat('not a', 'a = [5, 6, 7]', repeat=10))
0.04264092445373535
>>> min(timeit.repeat('not a', 'a = []', repeat=10))
0.04357004165649414
like image 345
SethMMorton Avatar asked Aug 31 '14 16:08

SethMMorton


People also ask

Which is faster bool or int?

Bool is smaller and hence can be faster if you are keeping large arrays of bools/ints, in terms of cache efficiency.

Is boolean faster than string?

Booleans and integers are fasterIntegers and Booleans are generally much faster than strings. If your calculation produces a binary result (for example, yes/no, pass/fail, over/under), be sure to return a Boolean result rather than a string.

What is bool in Python?

Python bool() Function The bool() function returns the boolean value of a specified object. The object will always return True, unless: The object is empty, like [], (), {} The object is False. The object is 0.

How do you know if Python is true or false?

You can check if a value is either truthy or falsy with the built-in bool() function. According to the Python Documentation, this function: Returns a Boolean value, i.e. one of True or False .


1 Answers

(This is not supposed to be an answer, just documentation): These are the byte code sequences of the given expressions:

bool(a):

1           0 LOAD_NAME                0 (bool)
            3 LOAD_NAME                1 (a)
            6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
            9 RETURN_VALUE

not a:

1           0 LOAD_NAME                0 (a)
            3 UNARY_NOT
            4 RETURN_VALUE

not not a:

1           0 LOAD_NAME                0 (a)
            3 UNARY_NOT
            4 UNARY_NOT
            5 RETURN_VALUE
like image 128
filmor Avatar answered Oct 26 '22 17:10

filmor