Question
Asked By – kramer65
I’ve got a in if-elif-elif-else statement in which 99% of the time, the else statement is executed:
if something == 'this':
doThis()
elif something == 'that':
doThat()
elif something == 'there':
doThere()
else:
doThisMostOfTheTime()
This construct is done a lot, but since it goes over every condition before it hits the else I have the feeling this is not very efficient, let alone Pythonic. On the other hand, it does need to know if any of those conditions are met, so it should test it anyway.
Does anybody know if and how this could be done more efficiently or is this simply the best possible way to do it?
Now we will see solution for issue: Most efficient way of making an if-elif-elif-else statement when the else is done the most?
Answer
The code…
options.get(something, doThisMostOfTheTime)()
…looks like it ought to be faster, but it’s actually slower than the if
… elif
… else
construct, because it has to call a function, which can be a significant performance overhead in a tight loop.
Consider these examples…
1.py
something = 'something'
for i in xrange(1000000):
if something == 'this':
the_thing = 1
elif something == 'that':
the_thing = 2
elif something == 'there':
the_thing = 3
else:
the_thing = 4
2.py
something = 'something'
options = {'this': 1, 'that': 2, 'there': 3}
for i in xrange(1000000):
the_thing = options.get(something, 4)
3.py
something = 'something'
options = {'this': 1, 'that': 2, 'there': 3}
for i in xrange(1000000):
if something in options:
the_thing = options[something]
else:
the_thing = 4
4.py
from collections import defaultdict
something = 'something'
options = defaultdict(lambda: 4, {'this': 1, 'that': 2, 'there': 3})
for i in xrange(1000000):
the_thing = options[something]
…and note the amount of CPU time they use…
1.py: 160ms
2.py: 170ms
3.py: 110ms
4.py: 100ms
…using the user time from time(1)
.
Option #4 does have the additional memory overhead of adding a new item for every distinct key miss, so if you’re expecting an unbounded number of distinct key misses, I’d go with option #3, which is still a significant improvement on the original construct.
This question is answered By – Aya
This answer is collected from stackoverflow and reviewed by FixPython community admins, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0