2011-08-11 3 views
30

クラスデコレータとメソッドデコレータを一緒にうまく組み合わせようとすると、この現象にぶつかりました。基本的に、メソッドデコレータはメソッドのいくつかをダミー値で特別なものにフラグを立て、クラスデコレータは後に来てその値を後で埋めます。 cow.moo.thing = 5が動作しない理由はPythonでinstancemethodsに属性を追加する

>>> class cow: 
>>>  def moo(self): 
>>>   print 'mooo' 
>>>  moo.thing = 10 
>>> 
>>> cow.moo.thing 
10 
>>> cow().moo.thing 
10 
>>> cow.moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow().moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow.moo.__func__.thing = 5 
>>> cow.moo.thing 
5 

簡略化した例である誰もがcow.moo.thingはかなり明確に私に10を与えるにもかかわらず、知っていますか?そして、なぜcow.moo.__func__.thing = 5が機能するのですか?私はそれがなぜ起こっているのか分かりませんが、無作為に何かを手に入れようとしているdir(cow.moo)のリストで突然それをやっていました。

答えて

33

属性ルックアップでは、Pythonはインスタンスメソッドに付属している実際の関数を自動的に使用します。

属性設定の場合は、設定しません。

これは、両方とも.演算子を使用していても、現在のステートメントのどちら側にあるかによって2つの別々の操作です。

インスタンスメソッドの__func__にアクセスすると、実際にmoo属性を持つ実関数に手動でアクセスしていることになります。

Python 3では、メソッドは基本的に単なる関数なので、/期待しているとおりに動作します。

+0

ああ、私は知らなかった。ありがとう! –

+0

古いポストをリバイブしていますが、Python3で 'cow()。moo.thing = 5'が' AttributeError: 'method'オブジェクトに属性 'thing'がありません。なぜなのかご存知ですか ? –

+0

@JacquesGaudinインスタンス( 'cow()。moo')では、関数はPythonのどのバージョンのメソッドオブジェクトにもラップされます。違いはクラス(' cow.moo')上です。ラッピングは 'self'が自動的に関数に渡されるために必要です。 – agf

3

Cから両方の関数とインスタンスメソッドの関数属性を変更する場合は、呼び出し可能な型をチェックする必要があります。今すぐコードAGFは、インスタンスメソッドのためのPythonの中から作品を指摘

PyObject *callable; // set to something callable 
PyObject *setting; // set to something 
if(PyMethod_Check(callable)){ 
    PyObject_SetAttrString(PyMethod_Function(callable),"attribute",setting); 
}else{ 
    PyObject_SetAttrString(callable,"attribute",setting); 
} 
... 
// and the inverse 
if(PyMethod_Check(callable){   
    if(PyObject_HasAttrString(PyMethod_Function(callable),"attribute")){ 
     PyObject_DelAttrString(PyMethod_Function(callable),"attribute"); 
    } 
    }else{ 
    if(PyObject_HasAttrString(callable,"attribute")){ 
     PyObject_DelAttrString(callable,"attribute"); 
    } 
    } 

だからあなたはこのようにそれを確認することができますが、呼び出し可能ないくつかの種類のPyObjectを持っていると仮定します。インスタンスメソッドの属性を設定しようとすると、Pythonからどのようにアクセスしようとしても、属性を見つけることはできません。

私はこの問題に遭遇しました。そして、Li Haoyiの質問はagfの答えで私が変更が必要なことを理解するのに役立ちました。

編集: 注:これはPython 2.7.x用です。この問題を解決するには、次の手順を実行します。 Python 3.xは異なる関数呼び出しを使用します。

関連する問題