33

クラス デコレータとメソッド デコレータをうまく連携させようとしたときに、この動作に遭遇しました。基本的に、メソッド デコレーターはいくつかのメソッドに特別なダミー値を付けてフラグを立て、クラス デコレーターは後で来て、後で値を入力します。これは簡単な例です

>>> 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

明らかに10が得られますが、なぜcow.moo.thing = 5機能しないのか誰かが知っていますか? cow.moo.thingそして、なぜcow.moo.__func__.thing = 5機能するのですか?理由はわかりませんが、dir(cow.moo)何かを機能させようとしてリスト内のものをランダムにいじっていると、突然機能し、理由がわかりません。

4

2 に答える 2

36

属性検索の場合、Python はインスタンス メソッドに関連付けられた実際の関数を自動的に使用します。

属性設定の場合はありません。

どちらも演算子を使用していますが、ステートメントのどちら側にいるかに応じて、これらは 2 つの別個の操作です.

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

Python 3 では、メソッドは基本的に単なる関数であるため、これは期待どおりに機能します。

于 2011-08-11T23:23:30.013 に答える
3

C から関数とインスタンス メソッドの両方の関数属性を変更する場合は、呼び出し可能な型を確認する必要があります。

したがって、あるタイプの callable の PyObject があると仮定すると、次のように確認できます。

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");
     }
  }  

agf が指摘したコードは、インスタンス メソッドの Python 内から機能します。インスタンス メソッドの属性を設定しようとすると、Python からどのようにアクセスしようとしても属性が見つかりません。

私はこの問題に遭遇し、Li Haoyi の質問と agf の回答は、何を変更する必要があるかを理解するのに役立ちました。Cでこの問題を解決する方法を探しているときに、誰かがこの質問を見つけてもう一度答えてくれると思いました.

編集: 注: これは Python 2.7.x 用です。Python 3.x は異なる関数呼び出しを使用します。

于 2012-12-02T15:03:35.117 に答える