#はじめに
既存のパッケージを少しだけ変えて使いたい。そんなときに役に立つのがモンキーパッチです。今回はモンキーパッチをする際にハマってしまったことがあるので、その理由と解決策を記載しておこうと思います。
ハマったこと
モンキーパッチをしても、メソッドが上書きできない。それが今回のハマったことです。状況を簡潔に再現するためにA.py, B.pyを以下のようなファイルとします。
def func_a(i):
return i
from A import func_a
def func_b(i):
return func_a(i)
要するにA.pyで作ったメソッドをB.pyにimportして使用しています。このとき、実行結果は以下のようになります。
import B
print(B.func_b(1))
#実行結果:1
ここまでは特に問題なく動きます。さて、ここでfunc_aをモンキーパッチによって上書きします。
import A
import B
#上書きするメソッド
def func_a_alt(i):
return 10*i
#モンキーパッチ!
A.func_a = func_a_alt
print(func_c(1))
#A.func_aをfunc_a_altで上書きしたから10が表示されるはず!
#実行結果:1
func_aをfunc_a_altで上書きしようとしたのにうまくいきませんでした。なぜだ...?
原因
原因はB.pyで
from A import func_a
をしていたことでした。これをすると、元々A.pyで定義したfunc_aと別のメモリに新しくfunc_aが記録されるみたいです。したがって、main2.pyを実行すると以下のような現象が起きます。
import A
import B #B.pyのfunc_aがA.pyのfunc_aとは別のメモリにできる
#上書きするメソッド
def func_a_alt(i):
return 10*i
#モンキーパッチ!
A.func_a = func_a_alt #A.pyのfunc_aだけ上書きされる
print(func_b(1)) #B.pyのfunc_aは上書きされていないから上書きされる前のメソッドが呼び出される
#実行結果:1
解決策
解決策は意外と簡単で、A.pyのfunc_aを上書きしたあとにB.pyを実行(import)するだけです。
import A
#ここではBをimportしない
#上書きするメソッド
def func_a_alt(i):
return 10*i
#モンキーパッチ!
A.func_a = func_a_alt #A.pyのfunc_aが上書きされる
import B #B.pyのfunc_aが上書きされた状態でimportされる
print(func_b(1))
#実行結果:10
#無事にモンキーパッチできました!
終わりに
モンキーパッチをする際には
- おおもとのメソッドを上書きする
- 他の.pyからメソッドを呼び出す前に上書きする
この2点を気を付ける必要があるようです。今回は簡単なスクリプトで再現しましたが、私は既存のパッケージに対してモンキーパッチしようとしてはまりました。私のハマり経験が何かのお役に立てれば嬉しいです!