1. ホーム
  2. python

[解決済み] Pythonで関数にパッチを当てるには?

2023-07-08 21:36:28

質問

別のモジュールの関数を別の関数に置き換えるのに苦労しており、気が狂いそうです。

例えば、次のようなモジュールbar.pyがあるとします。

from a_package.baz import do_something_expensive

def a_function():
    print do_something_expensive()

そして、もう一つ、こんな感じのモジュールがあります。

from bar import a_function
a_function()

from a_package.baz import do_something_expensive
do_something_expensive = lambda: 'Something really cheap.'
a_function()

import a_package.baz
a_package.baz.do_something_expensive = lambda: 'Something really cheap.'
a_function()

という結果が得られると予想されます。

Something expensive!
Something really cheap.
Something really cheap.

しかし、その代わりにこうなる。

Something expensive!
Something expensive!
Something expensive!

私は何を間違えているのでしょうか?

どうすればいいのでしょうか?

Pythonの名前空間がどのように機能するかを考えるのに役立つかもしれません: それは本質的に辞書です。 ですから、これを実行するとき

from a_package.baz import do_something_expensive
do_something_expensive = lambda: 'Something really cheap.'

はこのように考えてください。

do_something_expensive = a_package.baz['do_something_expensive']
do_something_expensive = lambda: 'Something really cheap.'

うまくいけば、なぜこれがうまくいかないのかがわかると思います :-) 名前を名前空間にインポートすると、インポートした名前空間での名前の値は から の名前の値は関係ありません。 ローカルモジュールの名前空間、つまり上記の a_package.baz の名前空間にある do_something_expensive の値を変更するだけです。 しかし、barはモジュールの名前空間から参照するのではなく、do_something_expensiveを直接インポートしているので、その名前空間に書き込む必要があります。

import bar
bar.do_something_expensive = lambda: 'Something really cheap.'