Choosing the Function Dynamically
我有一些代码如下所示:
1 2 3 4 5 6 | 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_u[command](a,b,c)中,调用的函数依赖于该命令的一些内容?
有可能吗?
您可以在dict中存储命令,并在需要时进行查找:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
您应该检查
1 2 3 4 | if command in commands: commands[command]() else: # handle error |
1 2 3 4 5 6 | 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 |
用途:
1 2 | do('a')(1,2,3) 6 |
您可以使用"反射"执行类似的操作,通过字符串名称调用函数,如下所示:
python:从字符串名称调用函数
但是
如果您不能完全控制作为
你的版本很好:
Explicit is better than implicit.
Simple is better than complex.
如果您真的想避免使用
像这样的事情,离埃瓦尔远点。
这可能有助于您,这里souce可以是任何以函数名结尾的通用模块路径,如模函数
因此,示例调用看起来像convertStringToFunction(module.funcname)
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
我在等待其他人提出更好的解决方案,但:
1 2 3 4 | def dispatch(cmd, *args): globals()['do_' + cmd](*args) def do_a(a, b, c): |
用途:
1 | dispatch('a', 1, 2, 3) |
显然不健壮,但是
一个很好的方法可能是使用装饰师。
1 2 3 4 5 6 7 | @command() def do_a(a,b,c): ... @command("do_x") def myfunc(a, b, c): ... |
您的装饰师可以维护分派查找表等。
这取决于您有多担心可能需要使用现有函数或担心名称冲突。