回答:
いいえ、それはそれらのどれとも似ていません。これは、単に実行時に属性を動的に置き換えることです。
たとえば、メソッドを持つクラスを考えてみましょうget_data
。このメソッドは(データベースやWeb APIなどで)外部ルックアップを行い、クラス内の他のさまざまなメソッドがそれを呼び出します。ただし、単体テストでは、外部データソースに依存したくないので、get_data
メソッドを、固定データを返すスタブで動的に置き換えます。
Pythonクラスは変更可能であり、メソッドはクラスの属性にすぎないため、好きなだけこれを行うことができます。実際、モジュール内のクラスと関数をまったく同じ方法で置き換えることもできます。
ただし、コメンターが指摘したように、モンキーパッチを適用するときには注意が必要です。
テストロジック以外に何かが呼び出さget_data
れた場合、元のコードではなく、サルがパッチを適用したものも呼び出されます。注意してください。
変数または属性が存在しget_data
、それを置き換えるときに関数も指している場合、このエイリアスはその意味を変更せず、元のを指し続けget_data
ます。(なぜですか?Pythonはget_data
クラス内の名前を他の関数オブジェクトに再バインドするだけです。他の名前バインディングはまったく影響を受けません。)
pointing to the original get_data function
ですか?誰かがその関数を変更した場合、変数内に関数を格納すると、変数は引き続き古い関数を指しますか?
get_data
を実行すると、名前get_data
をモック関数に再バインドします。プログラム内の別の場所にある他の名前が-former-formerly-known-as- get_data
にバインドされている場合、その他の名前については何も変更されません。
MonkeyPatchは、実行時(通常は起動時)に他のコードを拡張または変更するPythonコードの一部です。
簡単な例は次のようになります:
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
出典: Zope wikiのMonkeyPatchページ。
サルパッチとは何ですか?
簡単に言うと、モンキーパッチは、プログラムの実行中にモジュールまたはクラスに変更を加えることです。
Pandasのドキュメントにサルパッチの例があります。
import pandas as pd
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
これを分解するには、まずモジュールをインポートします。
import pandas as pd
次に、メソッド定義を作成します。これは、バインドされておらず、クラス定義のスコープ外で解放されています(関数とバインドされていないメソッドの区別はほとんど意味がないため、Python 3はバインドされていないメソッドを使用しません)。
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
次に、そのメソッドを使用したいクラスに単純にアタッチします。
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
次に、クラスのインスタンスでメソッドを使用し、完了したらメソッドを削除します。
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
名前マングリングを使用している場合(属性にプレフィックスとして二重下線を付けると、名前が変わるため、お勧めしません)、これを行う場合は手動で名前をマングルする必要があります。名前のマングリングはお勧めしませんので、ここでは説明しません。
たとえば、テストでこの知識をどのように使用できますか?
エラーの原因となる外部データソースへのデータ取得呼び出しをシミュレートする必要があるとしましょう。そのような場合に正しい動作を保証したいからです。この動作を確実にするために、サルにデータ構造をパッチすることができます。(したがって、Daniel Rosemanによって提案されたのと同様のメソッド名を使用します。)
import datasource
def get_data(self):
'''monkey patch datasource.Structure with this to simulate error'''
raise datasource.DataRetrievalError
datasource.Structure.get_data = get_data
そして、このメソッドがエラーを発生させることに依存する動作をテストすると、正しく実装されていれば、その動作がテスト結果に表示されます。
上記を実行するだけStructure
で、プロセスの存続期間中オブジェクトが変更されるため、ユニットテストでセットアップとティアダウンを使用して、それを回避する必要があります。例:
def setUp(self):
# retain a pointer to the actual real method:
self.real_get_data = datasource.Structure.get_data
# monkey patch it:
datasource.Structure.get_data = get_data
def tearDown(self):
# give the real method back to the Structure object:
datasource.Structure.get_data = self.real_get_data
上記の罰金ですが(おそらく、使用する良いアイデアだろうmock
コードにパッチを適用するライブラリを。mock
のpatch
デコレータは、上記を行うよりも発生しやすい小さいエラーになり、コードの複数行を必要とするので、エラーを導入するより多くの機会と思われます。まだコードを確認する必要はありませんmock
が、同様の方法でサルのパッチを使用していると思います。)
ウィキペディアによると:
Pythonでは、モンキーパッチという用語は、実行時にクラスまたはモジュールを動的に変更することのみを指し、既存のサードパーティコードに、意図したとおりに機能しないバグまたは機能の回避策としてパッチを当てようとする動機があります。
まず、サルのパッチは悪質なハックです(私の意見では)。
多くの場合、モジュールまたはクラスレベルのメソッドをカスタム実装で置き換えるために使用されます。
最も一般的な使用例は、元のコードを置き換えることができない場合に、モジュールまたはクラスのバグの回避策を追加することです。この場合、サルのパッチを適用して「間違った」コードを独自のモジュール/パッケージ内の実装に置き換えます。
モンキーパッチは動的言語でのみ実行できます。Pythonはその良い例です。オブジェクト定義を更新するのではなく、実行時にメソッドを変更することは1つの例です。同様に、実行時に属性(メソッドまたは変数)を追加することは、モンキーパッチと見なされます。これらはソースのないモジュールを操作するときによく行われ、オブジェクト定義を簡単に変更できないようにします。
これは、オブジェクトの定義が実際にどのように動作するかを完全または正確に記述していないことを意味するため、悪いと考えられています。
モンキーパッチとは何ですか?モンキーパッチは、実行時にコードの一部の動作を動的に更新するために使用される手法です。
モンキーパッチを使用する理由 実際にソースコードを変更せずに、実行時にライブラリ、モジュール、クラス、またはメソッドの動作を変更または拡張できます。
まとめモンキーパッチは優れた手法であり、Pythonでこれを行う方法を学びました。ただし、前述したように、この方法には固有の欠点があり、慎重に使用する必要があります。
詳細については、[1]を参照してください:https : //medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505
Monkey patching is a technique to add, modify, or suppress the default behavior of a piece of code at runtime without changing its original source code.