Created
June 17, 2021 15:16
-
-
Save paul-butcher/7dd84fcbd71e3c8f5100481c14a5993d to your computer and use it in GitHub Desktop.
A demonstration of using a dict of callables instead of a chain of if/elif/elif branches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from timeit import timeit | |
| import string | |
| # If you have a chain of if and elif like this | |
| # that you then use to decide a particular | |
| # course of action | |
| def ifelif(arg1, arg2): | |
| if arg1 == 'hello': | |
| return 'hi ' + arg2 | |
| elif arg1 == 'namaskara': | |
| backwards_name = str(reversed(arg2)) | |
| return 'susvagata ' + backwards_name | |
| elif arg1 == 'may the force be with you': | |
| return 'and also with you' | |
| raise ValueError('unknown greeting') | |
| # You can instead create a dict, keyed on the greeting, with callables as the value. | |
| def backwards_welcome(name): | |
| backwards_name = str(reversed(name)) | |
| return 'susvagata ' + backwards_name | |
| # The dict should be created outside of the function, either as a member of the object, class or module. | |
| greetings = { | |
| 'hello': lambda x: 'hi ' + x, | |
| # If it undesirable to use lambda (e.g. side-effects, too big, whatever) | |
| # define a function the old fashioned way. | |
| 'namaskara': backwards_welcome, | |
| # The callables must all have the same number of arguments, even if you don't use them | |
| # or you can use *args,**kwargs to allow variable args. | |
| 'may the force be with you': lambda _: 'and also with you', | |
| } | |
| # This makes the function look like this instead: | |
| def by_dict(arg1, arg2): | |
| try: | |
| return greetings[arg1](arg2) | |
| except KeyError: | |
| raise ValueError('unknown greeting') | |
| # At this scale, it doesn't make any difference to performance, | |
| # So the choice is purely cosmetic, and subject to personal preference. | |
| print('by ifs, first branch') | |
| print(timeit(lambda: ifelif('hello', 'paul'))) | |
| print('by dict, first entry') | |
| print(timeit(lambda: by_dict('hello', 'paul'))) | |
| print('by ifs, last branch') | |
| print(timeit(lambda: ifelif('may the force be with you', 'paul'))) | |
| print('by dict, last entry') | |
| print(timeit(lambda: by_dict('may the force be with you', 'paul'))) | |
| def bigif(arg): | |
| if(arg is None): return None | |
| elif(arg =="a"): return "hello" | |
| elif(arg =="b"): return "hello" | |
| elif(arg =="c"): return "hello" | |
| elif(arg =="d"): return "hello" | |
| elif(arg =="e"): return "hello" | |
| elif(arg =="f"): return "hello" | |
| elif(arg =="g"): return "hello" | |
| elif(arg =="h"): return "hello" | |
| elif(arg =="i"): return "hello" | |
| elif(arg =="j"): return "hello" | |
| elif(arg =="k"): return "hello" | |
| elif(arg =="l"): return "hello" | |
| elif(arg =="m"): return "hello" | |
| elif(arg =="n"): return "hello" | |
| elif(arg =="o"): return "hello" | |
| elif(arg =="p"): return "hello" | |
| elif(arg =="q"): return "hello" | |
| elif(arg =="r"): return "hello" | |
| elif(arg =="s"): return "hello" | |
| elif(arg =="t"): return "hello" | |
| elif(arg =="u"): return "hello" | |
| elif(arg =="v"): return "hello" | |
| elif(arg =="w"): return "hello" | |
| elif(arg =="x"): return "hello" | |
| elif(arg =="y"): return "hello" | |
| elif(arg =="z"): return "hello" | |
| elif(arg =="A"): return "hello" | |
| elif(arg =="B"): return "hello" | |
| elif(arg =="C"): return "hello" | |
| elif(arg =="D"): return "hello" | |
| elif(arg =="E"): return "hello" | |
| elif(arg =="F"): return "hello" | |
| elif(arg =="G"): return "hello" | |
| elif(arg =="H"): return "hello" | |
| elif(arg =="I"): return "hello" | |
| elif(arg =="J"): return "hello" | |
| elif(arg =="K"): return "hello" | |
| elif(arg =="L"): return "hello" | |
| elif(arg =="M"): return "hello" | |
| elif(arg =="N"): return "hello" | |
| elif(arg =="O"): return "hello" | |
| elif(arg =="P"): return "hello" | |
| elif(arg =="Q"): return "hello" | |
| elif(arg =="R"): return "hello" | |
| elif(arg =="S"): return "hello" | |
| elif(arg =="T"): return "hello" | |
| elif(arg =="U"): return "hello" | |
| elif(arg =="V"): return "hello" | |
| elif(arg =="W"): return "hello" | |
| elif(arg =="X"): return "hello" | |
| elif(arg =="Y"): return "hello" | |
| elif(arg =="Z"): return "hello" | |
| bigdict = {k: lambda: 'hello' for k in string.ascii_letters} | |
| # When you have a large set of choices, the dict wins hands down. | |
| print('by ifs, first branch, big selection') | |
| print(timeit(lambda: bigif('A'))) | |
| print('by dict, first entry, big_selection') | |
| print(timeit(lambda: bigdict['A']())) | |
| print('by ifs, last branch, big selection') | |
| print(timeit(lambda: bigif('Z'))) | |
| print('by dict, last entry, big_selection') | |
| print(timeit(lambda: bigdict['Z']())) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment