I am trying to understand descriptors better.
I don't understand why in the foo method the descriptors __get__
method doesn't get called.
As far as I understand descriptors the __get__
method always get called when I access the objects attribute via dot operator or when I use __getattribute__()
.
According to the Python documentation:
class RevealAccess(object):
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print('Retrieving', self.name)
return self.val
def __set__(self, obj, val):
print('Updating', self.name)
self.val = val
class MyClass(object):
x = RevealAccess(10, 'var "x"')
y = 5
def foo(self):
self.z = RevealAccess(13, 'var "z"')
self.__getattribute__('z')
print(self.z)
m = MyClass()
m.foo()
m.z # no print
m.x # prints var x
z
is an attribute on the instance, not on the class. The descriptor protocol only applies to attributes retrieved from a class.
From the Descriptor HOWTO:
For objects, the machinery is in
object.__getattribute__()
which transformsb.x
intotype(b).__dict__['x'].__get__(b, type(b))
.
and in the Implementing Descriptors section of the Python Data Model:
The following methods only apply when an instance of the class containing the method (a so-called descriptor class) appears in an owner class (the descriptor must be in either the owner’s class dictionary or in the class dictionary for one of its parents).
Your m.z
cannot be found in the class dict; type(m).__dict__['z']
does not exist; it is found in m.__dict__['z']
instead. Here m
is the instance and the owner class is MyClass
, and z
does not appear in the owner class dictionary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With