10

クラスインスタンスにメソッドを追加する場合、次のような単純な割り当てを行うことはできません。

>>> def print_var(self): # method to be added
        print(self.var)
>>> class MyClass:
        var = 5
>>> c = MyClass()
>>> c.print_var = print_var

これは確かにprint_var通常の関数のように動作するため、self引数は彼の典型的な意味を持ちません。

>>> c.print_var
<function print_var at 0x98e86ec>
>>> c.print_var()
Traceback (most recent call last):
  File "<pyshell#149>", line 1, in <module>
    c.print_var()
TypeError: print_var() takes exactly 1 argument (0 given)

関数をメソッドと見なす(つまり、インスタンスにバインドする)ために、私は次のコードを使用していました。

>>> import types
>>> c.print_var = types.MethodType(print_var, c)
>>> c.print_var
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>>
>>> c.print_var()
5

.__get__しかし、私はそれがこの目的にも使用できることを発見しました:

>>> c.print_var = print_var.__get__(c)
>>> c.print_var
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>>
>>> c.print_var()
5

ここでの問題は、それが正しく機能することですが、その方法と理由がわかりません。に関するドキュメント.__get__はあまり役に立たないようです。

誰かがPythonのインタプリタのこの振る舞いを明らかにしてくれれば幸いです。

4

1 に答える 1

9

あなたが探している情報は、記述子ハウツーガイドにあります:

メソッド呼び出しをサポートするために、関数には、__get__()属性アクセス中にメソッドをバインドするためのメソッドが含まれています。これは、すべての関数が非データ記述子であり、オブジェクトから呼び出されたかクラスから呼び出されたかに応じて、バインドされたメソッドまたはバインドされていないメソッドを返すことを意味します。純粋なPythonでは、次のように機能します。

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj)

したがって、実際には何も奇妙なことは起こっていません。__get__関数オブジェクトのメソッドが呼び出しtypes.MethodTypeて結果を返します。

于 2011-09-20T20:30:57.457 に答える