Reputation: 19507
I have an application where I need to be able to distinguish between numbers and bools as quickly as possible. What are the alternatives apart from running isinstance(value, bool)
first?
Edit:
Thanks for the suggestions. Actually, what I want to be able to do have a check for numbers that leaves out bools so that I can reorder my checks (numbers are far more prevalent) and improve my negacalls. isinstance()
itself is fast enough. The x is True or x is False
is intriguing.
Upvotes: 5
Views: 144
Reputation: 82734
So, Padraic Cunningham suggests, that the following might be a bit faster. My own quick experiments with cProfile
-ing it haven't shown any difference:
isbool = value is True or value is False
I assume that's as fast as you can get: Two non-type-coercing comparisons.
Edit: I replayed the timing tests from @user 5061 and added my statement. This is my result:
>>> import timeit
>>> stmt1 = "isinstance(123, bool)"
>>> stmt2 = "123 is True or 123 is False"
>>> t1 = timeit.timeit(stmt1)
>>> t2 = timeit.timeit(stmt2)
>>> print t1
0.172112941742
>>> print t2
0.0690350532532
Edit 2: Note, that I'm using Python 2.7 here. @user 5061 might use Python 3 (telling from the print()
function), so any solution provided here should be tested by OP before putting in production, for YMMV.
Upvotes: 5
Reputation: 5696
Testing done using Python 3.4.
stmt5
was suggested by grc.
stmt3
was suggested by boldewyn and seems to be the fastest option in most cases (unless data consists mostly of ints):
import timeit
setup = "a = 123; b = True"
stmt1 = "isinstance(a, bool) ; isinstance(b, bool)"
stmt2 = "isinstance(a, int) ; isinstance(b, int)"
stmt3 = "a is True or a is False; b is True or b is False"
stmt4 = "type(a) is bool; type(b) is bool"
stmt5 = "a.__class__ is bool ; b.__class__ is bool"
repetitions = 10**6
t1 = timeit.timeit(stmt1, setup=setup, number=repetitions)
t2 = timeit.timeit(stmt2, setup=setup, number=repetitions)
t3 = timeit.timeit(stmt3, setup=setup, number=repetitions)
t4 = timeit.timeit(stmt4, setup=setup, number=repetitions)
t5 = timeit.timeit(stmt5, setup=setup, number=repetitions)
print(t1)
print(t2)
print(t3)
print(t4)
print(t5)
Results:
0.251072
0.190989
0.037483
0.140759
0.08480
Note that isinstance(123, bool)
is slower than isinstance(123, int)
. Therefore i had to use both a
and b
. This is of course assuming that you have an equal amount of ints and bools.
Also, as grc suggested in the comments "True is faster because it short-circuits after the first comparison", so if you use b = False
you ll get a slightly slower time for stmt3
.
Only usable if the data does not contain 0, 0.0, 1, 1.0
:
setup = "a = 123; b = True; s = {True, False}"
stmt3 = "a is True or a is False; b is True or b is False"
stmt6 = "a in s ; b in s"
Result:
0.037680588
0.03936778
If your data consists mostly of integers, this becomes the fastest option (0.045375
vs 0.0390963
).
Upvotes: 3