記述子を定義すると、値の取得などがオーバーライドされ、記述子のインスタンスに事実上アクセスできなくなります。
つまり、書くことはできませんinstance_with_descriptor_attr.descriptor_attr.some_method_on_descriptor()
...動作しません。私の質問は、基本的に、どのようにして記述子のインスタンスにアクセスできるかということです...
記述子を定義すると、値の取得などがオーバーライドされ、記述子のインスタンスに事実上アクセスできなくなります。
つまり、書くことはできませんinstance_with_descriptor_attr.descriptor_attr.some_method_on_descriptor()
...動作しません。私の質問は、基本的に、どのようにして記述子のインスタンスにアクセスできるかということです...
eryksunが指摘しているように、Martijnのソリューションはプロパティに対して機能しますが、すべての記述子に対して機能するわけではありません。
class Desc(object):
def __init__(self, val=None):
self.val = val
def __get__(self, obj, cls):
return self.val
def __set__(self, obj, val):
self.val = val
class Test(object):
x = Desc(5)
>>> o = Test()
>>> print o.x
5
>>> print Test.x
5
プロパティ記述子で機能する理由は、ドキュメントのプロパティ記述子の実装例で確認できます:http: //docs.python.org/2/howto/descriptor.html#properties
重要なのは__get__
機能です。
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError, "unreadable attribute"
return self.fget(obj)
objがNoneの場合、記述子自体のインスタンスであるselfを返します。objは、記述子にアクセスするクラスのインスタンスです。クラスインスタンスから属性にアクセスする場合、objはそのインスタンスであり、クラスオブジェクトから属性にアクセスする場合、objはNoneです。
前の記述子を次のように変更します。
class Desc(object):
def __init__(self, val=None):
self.val = val
def __get__(self, obj, cls):
if obj is None:
return self
return self.val
def __set__(self, obj, val):
self.val = val
class Test(object):
x = Desc(5)
イールド(Pythonシェルを使用している場合は、クラスを再定義する必要があります)
o = Test()
>>> print o.x
5
>>> print Test.x
<__main__.Desc object at 0x23205d0>
あなたはクラス自体に行く必要があります:
type(instance_with_descriptor_attr).descriptor_attr
デモンストレーション:
>>> class Foo():
... @property
... def bar(self): return 'bar'
...
>>> foo = Foo()
>>> foo.bar
'bar'
>>> type(foo).bar
<property object at 0x109f24310>
__get__
記述子のメソッドに""ステートメントがない場合、記述子にはクラスの属性return self
によってのみアクセスできます。__dict__
class descriptor:
def __get__(self, instance, owner=None):
return 1
class A:
d = descriptor()
a = A()
a.d # --> 1
A.d # --> 1
A.__dict__['d'] # --> <__main__.descriptor object at ...>