2016-07-20 4 views
1
>>> class A: 
...  def foo(self): 
...    print(self) 
... 
>>> 
>>> a = A() 
>>> a.foo() 
<__main__.A instance at 0x7f4399136cb0> 
>>> def foo(self): 
...  print(self) 
... 
>>> a.foo = foo 
>>> a.foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: foo() takes exactly 1 argument (0 given) 

私はPythonで猿のパッチを理解しようとしています。エラーの原因とその修正方法を説明してください。Pythonで猿のパッチを当てる方法

答えて

3

this SO answerで説明したように、あなたがこれを行う際に、例えばtypes.MethodTypeまたは類似のものを使用する必要があります。

a.foo = types.MethodType(foo, a) 

理由はa.foo = fooがちょうどaの属性として機能fooを設定していることである - ノー「魔法の結合" 終わらせる。 a.fooを呼び出すときにPythonが最初の引数としてインスタンスを「魔法のように」渡すようにするには、Pythonにそのようなバインディングを行うように指示する必要があります。 types.MethodTypeを使用してください。

詳細については上記の回答をご覧ください。

1

だからここにトリッキーな事は何を得るの方法が住んでいる場所に依存していることである:あなたがこれを実行すると、あなたは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))ので、私たちはここでその呼び出しシーケンスを再生している(答えは、我々は属性として、それを追加するとき、それは記述プロトコルです使用しています明示的に)。

+0

ありがとうございます!サルのパッチ適用にディスクリプタプロトコルが必要ない場合はありますか?この例では、https://github.com/yasoob/intermediatePython/blob/master/args_and_kwargs.rst#when-to-use-themの人はそれを使用せず、それはまだ動作します。 –

+0

@AbhishekBhatia - インスタンスを作成する前にクラスにパッチを当てる必要はありません: 'A.foo = patch; a = A(); a.foo() ' - しかし、もしあなたが実際にたくさんのパッチを当てようとしているのであれば、それはちょうどテスト中だと思うし、モックライブラリを使ってそれをやることをお勧めします(例えば、'モック ') – mgilson

+0

ありがとう!別々のライブラリを作成するようにアドバイスした理由を説明できますか?私はあなたを理解しているか分からない。 –

関連する問題