Pythonプロパティを正常に使用しましたが、どのように機能するかわかりません。クラス外のプロパティを逆参照すると、タイプproperty
:
@property
def hello(): return "Hello, world!"
hello # <property object at 0x9870a8>
ただし、クラスにプロパティを配置すると、動作が大きく異なります。
class Foo(object):
@property
def hello(self): return "Hello, world!"
Foo().hello # 'Hello, world!'
バインドされていないFoo.hello
はproperty
オブジェクトのままなので、クラスのインスタンス化は魔法を行う必要がありますが、それはどのような魔法ですか?
他の人が指摘したように、彼らは記述子と呼ばれる言語機能を使用します。
クラス_Foo.hello
_を介してアクセスしたときに実際のプロパティオブジェクトが返される理由は、プロパティが__get__(self, instance, owner)
特殊メソッドを実装する方法にあります。
owner
はそのインスタンスのクラス。instance
はNoneであり、owner
のみが渡されます。 property
オブジェクトはこれを認識し、self
を返します。Descriptors howto の他に、言語ガイドの Implementing Descriptors および Invoking Descriptors に関するドキュメントも参照してください。
@propertiesが適切に機能するためには、クラスはobjectのサブクラスである必要があります。クラスがobjectのサブクラスではない場合、セッターに初めてアクセスすると、セッターを介してアクセスするのではなく、実際には短い名前で新しい属性が作成されます。
以下はnotが正しく動作します。
class C(): # <-- Notice that object is missing
def __init__(self):
self._x = None
@property
def x(self):
print 'getting value of x'
return self._x
@x.setter
def x(self, x):
print 'setting value of x'
self._x = x
>>> c = C()
>>> c.x = 1
>>> print c.x, c._x
1 0
以下は正しく動作します
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
print 'getting value of x'
return self._x
@x.setter
def x(self, x):
print 'setting value of x'
self._x = x
>>> c = C()
>>> c.x = 1
setting value of x
>>> print c.x, c._x
getting value of x
1 1
プロパティは descriptors であり、クラスインスタンスのメンバーの場合、ディスクリプタは特別に動作します。つまり、a
がA
型のインスタンスであり、A.foo
が記述子の場合、a.foo
はA.foo.__get__(a)
と同等です。
property
オブジェクトは、記述子プロトコルを実装するだけです。 http://docs.python.org/howto/descriptor.html