动态选择功能

时间:2013-02-07 11:15:53

标签: python

我有一些代码如下:

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)这样的东西,被调用的函数依赖于命令?

甚至可能吗?

5 个答案:

答案 0 :(得分:2)

您可以在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

你应该检查一下command是否确实在commands

if command in commands:
    commands[command]()
else:
    # handle error

答案 1 :(得分:1)

您可以使用“反射”执行类似的操作,通过字符串名称调用函数,如下所述:

Python: call a function from string name

<强> BUT

如果你对command传递的内容没有绝对的控制权,那就不会更优雅了,它会更不易读,更容易搞砸。

你的版本很好:

  

明确比隐含更好。

     

简单比复杂更好。

如果你真的想避开elif,我会选择评论中建议的dict函数方法。

远离eval这样的事情。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

我正在等待其他人提供更好的解决方案,但是:

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):
   ...

您的装饰者可以维护调度查找表等。

这取决于您是否担心可能需要使用现有功能或担心名称冲突。

答案 4 :(得分:0)

这可能对你有帮助,这里的源可以是任何以函数名结尾的通用模块路径 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