だからここにトリッキーな事は何を得るの方法が住んでいる場所に依存していることである:あなたがこれを実行すると、あなたはpython2.xおよび3.xで異なる結果が得られます
class A(object):
def foo(self):
print("Hello world")
def patch(self):
print("patched!")
print(type(A.foo))
a = A()
print(type(a.foo))
:
$ python ~/sandbox/test.py # python2.x
<type 'instancemethod'>
<type 'instancemethod'>
$ python3 ~/sandbox/test.py # python3.x
<class 'function' at 0x100228020>
<class 'method' at 0x10021d0c0>
どちらの場合でも、a.foo
が何らかの方法であることは明らかです。
サルのパッチを当てようとするとどうなりますか?
a.foo = patch
print(type(a.foo)) # <type 'function'> (2.x)/<class 'function'> (3.x)
[OK]を、今はa.foo
はタイプfunction
(ない方法)であることがわかります。だから問題はどうやって「パッチ」を外に出す方法なのだろう?クラスのメソッドについては
a.foo = patch.__get__(a, A)
を、あなたがa.some_method
を行う際に、Pythonは実際に行われます:a.some_method.__get__(a, type(a))
ので、私たちはここでその呼び出しシーケンスを再生している(答えは、我々は属性として、それを追加するとき、それは記述プロトコルです使用しています明示的に)。
ありがとうございます!サルのパッチ適用にディスクリプタプロトコルが必要ない場合はありますか?この例では、https://github.com/yasoob/intermediatePython/blob/master/args_and_kwargs.rst#when-to-use-themの人はそれを使用せず、それはまだ動作します。 –
@AbhishekBhatia - インスタンスを作成する前にクラスにパッチを当てる必要はありません: 'A.foo = patch; a = A(); a.foo() ' - しかし、もしあなたが実際にたくさんのパッチを当てようとしているのであれば、それはちょうどテスト中だと思うし、モックライブラリを使ってそれをやることをお勧めします(例えば、'モック ') – mgilson
ありがとう!別々のライブラリを作成するようにアドバイスした理由を説明できますか?私はあなたを理解しているか分からない。 –