I am new to Python and looking through its documentation I encountered the following example of the descriptor protocol that in my opinion is incorrect. .
It looks like
class IntField:def __get__(self, instance, owner):return instance.__dict__[self.name]def __set__(self, instance, value):if not isinstance(value, int):raise ValueError(f'expecting integer in {self.name}')instance.__dict__[self.name] = value# this is the new initializer:def __set_name__(self, owner, name):self.name = nameclass Model:int_field = IntField()
Here are my considerations.
The attribute int_field
is a class-wide attribute is not it?
So owner.__dict__
will have such a key. However in the method __get__
there is used instance.__dict__
that does not have that key. So from the point of view of using the method the method does not deal with the class-wide attribute but deals with an instance-wide attribute.
On the other hand, the method __set__
also does not deal with the class-wide attribute but creates an instance-wide attribute because there is used
instance.__dict__[self.name] = value
So it looks like each instance of the class creates its own instance-wide attribute. Moreover a reference to the class even is not passed to the method.
Am I right or do I have missed something that I do not know yet?
To make my considerations more clear the example logically is equivalent to the following
class MyClass:int_field = 10instance_of = MyClass();instance_of.__dict__["int_field"] = 20print( MyClass.int_field )
print( instance_of.int_field )
The program output is
10
20
The instance attribute int_field
has nothing common with the class-wide attribute int_field
except its name.
The same is true for the example from the documentation. Intuitively one can expect that it is the class-wide attribute that is attached to the descriptor. However it is not true. The descriptor just borrows the name of the class-wide attribute. On the other hand, a class-wide attribute can indeed be attached to a descriptor.
So the example from the documentation in my opinion just confuses readers.