1

我有一些如下所示的代码:

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) 的东西,被调用的函数取决于命令?

甚至可能吗?

4

5 回答 5

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

您应该检查 a 是否command确实在commands

if command in commands:
    commands[command]()
else:
    # handle error
于 2013-02-07T11:24:43.850 回答
1

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

Python:从字符串名称调用函数

如果您对传递的内容没有绝对控制权,那将不会更优雅,可读性会降低,并且更容易搞砸command.

你的版本很好:

显式优于隐式。

简单胜于复杂。

如果您真的想避免使用elif's,我会采用dict评论中建议的函数方法。

远离 eval 这样的事情。

于 2013-02-07T11:21:20.887 回答
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
于 2018-03-20T20:51:06.637 回答
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):
   ...

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

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

于 2013-02-07T11:39:14.983 回答
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
于 2013-02-07T11:48:48.500 回答