メソッドも属性です。それらはたまたま呼び出し可能なオブジェクトです。
callable()
関数を使用して、オブジェクトが呼び出し可能かどうかを検出できます。
>>> def foo(): pass
...
>>> callable(foo)
True
>>> callable(1)
False
getattr()
メソッドを呼び出すときは、属性 (操作)を検索してから結果を呼び出します。
c.setAttr(newvalue)
2つのステップです。属性を見つけて (この場合、クラスの属性を検索し、それを記述子として扱います)、結果のオブジェクトであるメソッドを呼び出します。
属性に割り当てるときは、その名前を新しい値に再バインドします。
c.setAttr = 'something else'
作戦だろうsetattr()
。
クラスのインスタンスで属性の取得と設定をインターセプトしたい場合は、属性アクセス フック、__getattr__
、__setattr__
および を提供できます__delattr__
。
インスタンスにメソッドを追加したい場合は、メソッド オブジェクトを生成する記述子オブジェクトとして関数を扱う必要があります。
>>> class Foo: pass
...
>>> foo = Foo() # instance
>>> def bar(self): pass
...
>>> bar
<function bar at 0x10b85a320>
>>> bar.__get__(foo, Foo)
<bound method Foo.bar of <__main__.Foo instance at 0x10b85b830>>
インスタンスとクラスが与えられた場合の の戻り値function.__get__()
は、バインドされたメソッドです。そのメソッドを呼び出すとself
、インスタンスにバインドされた基になる関数が呼び出されます。
記述子について言えば、property()
関数は記述子も返すため、属性のように振る舞う関数を持つことができます。getattr()
、setattr()
およびその属性の操作をインターセプトしdelattr()
て、関数呼び出しに変換できます。
>>> class Foo:
... @property
... def bar(self):
... return "Hello World!"
...
>>> foo = Foo()
>>> foo.bar
"Hello World!"
アクセスすると、プロパティの get フックが.bar
呼び出され、元のメソッドが呼び出されます。bar
bar
ほとんどの場合、このcallable()
関数は必要ありません。API を文書化し、メソッドと属性を提供すると、API のユーザーは、すべての属性をテストして呼び出し可能かどうかを確認することなく、それを理解します。プロパティを使用すると、どのような場合でも実際に呼び出し可能な属性を柔軟に提供できます。