我有一些如下所示的代码:
if command == 'a':
do_a(a, b, c)
elif command == 'b':
do_b(a, b, c)
elif command == 'c':
do_c(a, b, c)
我怎样才能用更优雅的东西代替这种类型的东西?也许,类似于 do_[command](a, b, c) 的东西,被调用的函数取决于命令?
甚至可能吗?
我有一些如下所示的代码:
if command == 'a':
do_a(a, b, c)
elif command == 'b':
do_b(a, b, c)
elif command == 'c':
do_c(a, b, c)
我怎样才能用更优雅的东西代替这种类型的东西?也许,类似于 do_[command](a, b, c) 的东西,被调用的函数取决于命令?
甚至可能吗?
您可以将命令存储在 dict 中并在需要时进行查找:
In [15]: commands = {'mul': lambda x,y: x*y,
'add': lambda x,y: x+y}
In [16]: commands['mul'](3,4)
Out[16]: 12
In [17]: commands['add'](3,4)
Out[17]: 7
In [18]: command = 'add'; vars = (4,5)
In [19]: commands[command](*vars)
Out[19]: 9
您应该检查 a 是否command
确实在commands
:
if command in commands:
commands[command]()
else:
# handle error
您可以使用“反射”执行类似的操作,通过字符串名称调用函数,如下所述:
但
如果您对传递的内容没有绝对控制权,那将不会更优雅,可读性会降低,并且更容易搞砸command
.
你的版本很好:
显式优于隐式。
简单胜于复杂。
如果您真的想避免使用elif
's,我会采用dict
评论中建议的函数方法。
远离 eval 这样的事情。
def do(fname):
return {'a':do_a, 'b':do_b, 'c':do_c}.get(fname)
def do_a(x,y,z): return x + y + z
def do_b(x,y,z): pass
def do_c(x,y,z): pass
用法:
do('a')(1,2,3)
6
我正在等待其他人提供更好的解决方案,但是:
def dispatch(cmd, *args):
globals()['do_' + cmd](*args)
def do_a(a, b, c):
用法:
dispatch('a', 1, 2, 3)
显然不健壮,但dispatch
可以确保该功能存在。
可能一个不错的方法是使用装饰器。
@command()
def do_a(a,b,c):
...
@command("do_x")
def myfunc(a, b, c):
...
您的装饰器可以维护调度查找表等。
这取决于您是否担心可能需要使用现有功能或担心名称冲突。
这可能会对您有所帮助,这里的源可以是任何以函数名称结尾的通用模块路径,例如 module.funcname
所以一个示例调用看起来像 convertStringToFunction(module.funcname)
def import_module(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
def convertStringToFunction(source):
tempArr = source.rsplit('.',1)
mod = import_module(tempArr[0])
func = getattr(mod, tempArr[1])
return func