次のようなコードがあります。
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 と 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
command
aが実際に にあるかどうかを確認する必要がありますcommands
。
if command in commands:
commands[command]()
else:
# handle error
ここで説明されているように、「リフレクション」を使用して、文字列名で関数を呼び出して、そのようなことを行うことができます。
しかし
として渡されるものを完全に制御できない場合、それはよりエレガントではなく、読みにくくなり、台無しになりやすくなりますcommand
。
あなたのバージョンは問題ありません:
明示的は暗黙的よりも優れています。
シンプルは複雑よりも優れています。
を本当に避けたい場合は、コメントで提案された関数のアプローチをelif
使用します。dict
このようなことについては eval を避けてください。
私は他の人からのより良い解決策を待っていますが:
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