Long elif chains vs dictionary with exec()
我是一个新手,我已经阅读了很多关于如何正确编码的教程。不断出现的一件事是永远不要多次编写同一行代码。我不确定长elif参数是否有意义,但对我来说,它看起来像是坏代码。
为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class answers(object): def __init__(self): self.x = 'hello world' def knight(self): print('Neee!') def bunny(self): print('Rawwww!') def pesant(self): print('Witch!') def dingo(self): print('Bad, wicked, naughty Zoot!') foo = answers() egg = input("Sounds:") if egg =="knight": foo.knight() elif egg == 'bunny': foo.bunny() elif egg == 'pesant': foo.pesant() elif egg == 'dingo': foo.dingo() else: print("I don't know?") |
这是可行的,但我认为下面的代码看起来更干净。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class answers(object): def __init__(self): self.x = 'hello world' def knight(self): print('Neee!') def bunny(self): print('Rawwww!') def pesant(self): print('Witch!') def dingo(self): print('Bad, wicked, naughty Zoot!') foo = answers() responce = {'knight': 'foo.knight()', 'bunny': 'foo.bunny()', 'pesant': 'foo.pesant()', 'dingo': 'foo.dingo()'} while True: try: egg = input('sounds:') exec(responce[egg]) except KeyError: print("I don't know") |
两行代码都做同样的事情,我使用哪一行真的很重要,还是一行比另一行更好?
注意,我知道exec()通常不应该被使用,但我找不到另一种方法来为字符串分配函数。
如果跳过
1 2 3 4 5 6 | responce = { 'knight': foo.knight, 'bunny': foo.bunny, 'pesant': foo.pesant, 'dingo': foo.dingo, } |
然后您可以使用
1 2 3 | responce[egg]() #responce[egg](arg1, arg2, ...) # if function require arguments |
全码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Answers(object): # CamelCase name for class - see PEP8 document def __init__(self): self.x = 'hello world' def knight(self): print('Neee!') def bunny(self): print('Rawwww!') def pesant(self): print('Witch!') def dingo(self): print('Bad, wicked, naughty Zoot!') foo = Answers() responce = { 'knight': foo.knight, 'bunny': foo.bunny, 'pesant': foo.pesant, 'dingo': foo.dingo, } while True: try: egg = input('sounds:') responce[egg]() # call function except KeyError: print("I don't know") |
btw:这样,您甚至可以使用函数名作为另一个函数的参数。
在Tkinter中用于将功能分配给按钮
1 | Button( ..., text="knight", command=foo.knight) |
或为事件分配函数
1 | bind('<Button-1>', foo.knight) |
如果需要用参数分配函数,那么可以使用
python3版本:
1 2 3 4 5 6 | responce = { 'knight': lambda:print('Neee!'), 'bunny': lambda:print('Rawwww!'), 'pesant': lambda:print('Witch!'), 'dingo': lambda:print('Bad, wicked, naughty Zoot!'), } |
python2版本:
python2中的
1 2 3 4 5 6 7 8 9 | def show(text): print text responce = { 'knight': lambda:show('Neee!'), 'bunny': lambda:show('Rawwww!'), 'pesant': lambda:show('Witch!'), 'dingo': lambda:show('Bad, wicked, naughty Zoot!'), } |
编辑:但如果字典中没有函数,我可以这样做:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | # --- classes --- class Answers(object): def __init__(self): # TODO: read it from file CSV or JSON # # import json # # with open("data.json") as f: # self.data = json.load(f) self.data = { 'knight': 'Neee!', 'bunny': 'Rawwww!', 'pesant': 'Witch!', 'dingo': 'Bad, wicked, naughty Zoot!', } def response(self, text): try: return self.data[text] except KeyError: return"I don't know" # --- functions --- # empty # --- main --- foo = Answers() while True: egg = input('sounds: ').lower() if egg == 'exit': break print(foo.response(egg)) # --- print("Good Bye!") |
Furas的伟大评论已经很好地涵盖了如何做到这一点,但至于为什么要这样做,有一个比"看起来更干净"更好的理由:
与case/switch语句或if/elif/else语句的长链相比,函数表的代码(无论是从编写的内容还是编译器或解释器生成的内容)往往更少。
它们也跑得更快。
因此,您对它的直觉"看起来更干净"是非常正确的,实际上,这是一种处理事情的方法,不仅在Python中,而且在任何编程语言中。