次のような変数に関数名を保存しています:
myvar = 'mypackage.mymodule.myfunction'
そして今、私はこのようにmyfunctionを呼び出したい
myvar(parameter1, parameter2)
これを達成する最も簡単な方法は何ですか?
funcdict = {
'mypackage.mymodule.myfunction': mypackage.mymodule.myfunction,
....
}
funcdict[myvar](parameter1, parameter2)
関数自体はPythonのファーストクラスオブジェクトであるため、関数自体を格納できる方がはるかに優れています。
import mypackage
myfunc = mypackage.mymodule.myfunction
myfunc(parameter1, parameter2)
ただし、パッケージを動的にインポートする必要がある場合は、次の方法でこれを実現できます。
mypackage = __import__('mypackage')
mymodule = getattr(mypackage, 'mymodule')
myfunction = getattr(mymodule, 'myfunction')
myfunction(parameter1, parameter2)
ただし、その作業はすべて現在のスコープに適用されることに注意してください。何らかの理由でそれらを永続化しないと、ローカルスコープを離れてもそれらが存続することを期待できません。
def f(a,b):
return a+b
xx = 'f'
print eval('%s(%s,%s)'%(xx,2,3))
[〜#〜] output [〜#〜]
5
最も簡単な
eval(myvar)(parameter1, parameter2)
関数「ポインター」がありません。関数「名前」があります。
これはうまく機能しますが、「安全ではない」または「セキュリティリスク」であると多くの人に言われます。
関数自体を保存しないのはなぜですか? myvar = mypackage.mymodule.myfunction
はずっときれいです。
modname, funcname = myvar.rsplit('.', 1)
getattr(sys.modules[modname], funcname)(parameter1, parameter2)
eval(compile(myvar,'<str>','eval'))(myargs)
compile(...、 'eval')は単一のステートメントのみを許可するため、呼び出し後に任意のコマンドを使用することはできません。そうしないと、SyntaxErrorが発生します。その後、ほんの少しの検証で、少なくとも「mypackage」のテストを開始するなど、表現をあなたの力のあるものに制約することができます。
認証を処理するライブラリを作成中に、同様の問題に遭遇しました。ライブラリを使用するアプリの所有者が、認証されたユーザーが属するLDAPグループに対する承認をチェックするためにライブラリにコールバックを登録できるようにしたいです。設定は、インポートされ、すべての構成パラメーター。
私はこれを機能させました:
>>> class MyClass(object):
... def target_func(self):
... print "made it!"
...
... def __init__(self,config):
... self.config = config
... self.config['funcname'] = getattr(self,self.config['funcname'])
... self.config['funcname']()
...
>>> instance = MyClass({'funcname':'target_func'})
made it!
これを行うPythonic-erの方法はありますか?