1. ホーム
  2. python

[解決済み] Pythonで他のモジュールにあるクラスを修正するモンキーパッチ

2023-03-20 08:53:51

質問

他の人が書いたモジュールで作業しています。私は __init__ メソッドにパッチを当てたいと思っています。私が見つけたこれを行う方法を示す例は、すべて私自身がクラスを呼び出すことを想定しています (例. モンキーパッチのPythonクラス ). しかし、これはそうではありません。私の場合、クラスは他のモジュールの関数の中で初期化されています。以下の(大幅に簡略化した)例を見てください。

thirdpartymodule_a.py

class SomeClass(object):
    def __init__(self):
        self.a = 42
    def show(self):
        print self.a

thirdpartymodule_b.py

import thirdpartymodule_a
def dosomething():
    sc = thirdpartymodule_a.SomeClass()
    sc.show()

mymodule.py

import thirdpartymodule_b
thirdpartymodule_b.dosomething()

を変更する方法はありますか? __init__ メソッドを修正する方法はありますか? SomeClass であるため dosomething が mymodule.py から呼び出されたとき、例えば42の代わりに43を表示するようにできますか?理想的には、私は既存のメソッドをラップすることができると思います。

他のスクリプトが既存の機能に依存しているので、私はthirdpartymodule*.pyファイルを変更することができません。私が行う必要がある変更は非常に単純であるため、私はむしろ、モジュールの私自身のコピーを作成する必要がないことを望みます。

編集 2013-10-24

上の例で、小さいけれども重要なことを見落としていました。 SomeClass がインポートされるのは thirdpartymodule_b のようにします。 from thirdpartymodule_a import SomeClass .

F.J が提案したパッチを適用するために、私は thirdpartymodule_b よりも、むしろ thirdpartymodule_a です。 thirdpartymodule_b.SomeClass.__init__ = new_init .

どのように解決するのですか?

以下のようにするとうまくいくはずです。

import thirdpartymodule_a
import thirdpartymodule_b

def new_init(self):
    self.a = 43

thirdpartymodule_a.SomeClass.__init__ = new_init

thirdpartymodule_b.dosomething()

新しいinitで古いinitを呼び出したい場合は、以下のように new_init() の定義を以下のように置き換えてください。

old_init = thirdpartymodule_a.SomeClass.__init__
def new_init(self, *k, **kw):
    old_init(self, *k, **kw)
    self.a = 43