The python 3.3 documentation tells me that direct access to a property descriptor should be possible, although I'm skeptical of its syntax
def __get__(self, instance, owner):
x = MyDescriptor()
if __name__ == '__main__':
my_instance = Owner()
Traceback (most recent call last):
File "descriptor_test.py", line 15, in <module>
File "descriptor_test.py", line 10, in do_direct_access
AttributeError: 'int' object has no attribute '__get__'
shell returned 1
By accessing the descriptor on
self you invoked
__get__ already. The value
42 is being returned.
For any attribute access, Python will look to the type of the object (so
type(self) here) to see if there is a descriptor object there (an object with a
.__get__() method, for example), and will then invoke that descriptor.
That's how methods work; a function object is found, which has a
.__get__() method, which is invoked and returns a method object bound to self.
If you wanted to access the descriptor directly, you'd have to bypass this mechanism; access
x in the
__dict__ dictionary of
>>> Owner.__dict__['x'] <__main__.MyDescriptor object at 0x100e48e10> >>> Owner.__dict__['x'].__get__(None, Owner) hello 42
This behaviour is documented right above where you saw the
x.__get__(a) direct call:
The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance,
a.xhas a lookup chain starting with
type(a).__dict__['x'], and continuing through the base classes of
The Direct Call scenario in the documentation only applies when you have a direct reference to the descriptor object (not invoked); the
Owner.__dict__['x'] expression is such a reference.
Your code on the other hand, is an example of the Instance Binding scenario:
If binding to an object instance,
a.xis transformed into the call: