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 と lookup に保存できます。

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

commandaが実際に にあるかどうかを確認する必要がありますcommands

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

ここで説明されているように、「リフレクション」を使用して、文字列名で関数を呼び出して、そのようなことを行うことができます。

Python: 文字列名から関数を呼び出す

しかし

として渡されるものを完全に制御できない場合、それはよりエレガントではなく、読みにくくなり、台無しになりやすくなりますcommand

あなたのバージョンは問題ありません:

明示的は暗黙的よりも優れています。

シンプルは複雑よりも優れています。

を本当に避けたい場合は、コメントで提案された関数のアプローチをelif使用します。dict

このようなことについては eval を避けてください。

于 2013-02-07T11:21:20.887 に答える
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 に答える