のようなセキュリティ ホールを除いて、名前がどこかで定義されているか、別のモジュールからインポートされていない限り、名前をeval
使用することはできません。別のモジュールからの値に自動的かつ静かにアクセスさせる方法はありません。a
mapper.py
mapper.py
mapper.py
a
さらに、例のように dict でのみ使用している場合はa.foo
、dict が作成されるとすぐに評価されます。実際に関数を呼び出すまで待つ必要はありません。辞書を作成するために評価されるとすぐに、何がa.foo
何であるかがわからないため失敗しa
ます。
この 2 番目の問題は、要素を関数でラップすることで回避できます (簡潔にするためにラムダを使用します)。
Mapper = {'test': lambda: a.foo}
. . . a
しかし、どうにかして内部で利用できるようにならない限り、これはまだ役に立ちませんmapper.py
。
1つの可能性は、「ミステリー」オブジェクトでパラメーター化Mapper
し、そのオブジェクトを外部から渡すことです。
# mapper.py
Mapper = {'test': lambda a: a.foo}
# other module
from mapper import Mapper
Mapper['test'](a)()
または、提案されたのと同様に、何らかの方法でオブジェクトをmgilson
「登録」できます。これにより、オブジェクトを一度だけ渡して登録することができ、呼び出しごとに渡す必要がなくなります。a
Mapper
a
# mapper.py
Mapper = {'test': lambda a: Mapper['a'].foo}
# other module
from mapper import Mapper
Mapper['a'] = a
Mapper['test']()()
最後に 2 組の括弧があることに注意してください。1 組はラムダを評価して呼び出したい関数を抽出するためのもので、2 番目の組は実際にその関数を呼び出すためのものです。参照として使用する代わりにMapper['a']
、モジュール レベルの変数を使用して、同様の処理を行うことができます。
# mapper.py
Mapper = {'test': lambda: a.foo}
# other module
import mapper
Mapper = mapper.Mapper
mapper.a = a
Mapper['test']()()
import mapper
これは、他のモジュールでモジュール変数を設定するために行う必要があることに注意してください。
Mapper
通常の dict の代わりにカスタムクラス for を使用し、そのクラス__getitem__
に「既知の場所」を調べて (たとえば、モジュール変数を読み取って) 評価のベースとして使用することで、これをいくらか合理化できa
ます。ただし、それはより重いソリューションになります。
肝心なのは、未定義の variable を使用するeval
コードを(再び、または他のそのような穴を使用せずに) 記述し、別のモジュールで変数を定義して、それを自動的に認識することができないということです。使用する値を「伝える」コード行がどこかにある必要があります。mapper.py
a
a
mapper.py
mapper.py
a