My question is loosely related to Why `self.__setattr__(attr, value)` trigger `__getattribute__`?
I’m struggling to understand the relationship between getattribute and write-descriptors
in the code below I add a descriptor to the Room class - skip over the descriptor it self, it’s not relevant
but at the point where self.desc = desc
, the system obviously finds out that desc
is a descriptor instance; so how does it find out, since it does not appear to call my __getattribute__
to this end ?
and on a similarly disconcerting note:
- I take it that
__getattribute__
itself is not searched through__getattribute__
either, so how exactly does that work ? - and the fact that
__dict__
on the other hand gets searched by__getattribute__
also blows my mind; I was not expecting that; I guess the descriptor should probably useobject.__getattr__
andobject.__setattr__
instead of messing directly intoinstance.__dict__
, what exactly are the differences, which one is better ?
# a standard attribute descriptor
class InstanceAttributeDescriptor:
def __set_name__(self, owner, name):
self.public_name = name
self.private_name = "_" + name
def __get__(self, instance, owner):
return instance.__dict__[self.private_name]
def __set__(self, instance, new_value):
instance.__dict__[self.private_name] = new_value
class Room:
desc = InstanceAttributeDescriptor()
def __init__(self, name, desc):
self.name = name
self.desc = desc
def __getattribute__(self, attr):
print("in __getattribute__", attr)
return object.__getattribute__(self, attr)
def __setattr__(self, attr, value):
print("in __setattr__", attr, value)
# time.sleep(3)
object.__setattr__(self, attr, value)
def __repr__(self):
return f"{self.name} ({self.desc})"
# just to make sure the descriptor indeed gets found along the mro
class SubRoom(Room):
pass
r = SubRoom("kitchen", "where to do the cooking")
print("--")
print(r)
which yields
in __setattr__ name kitchen
in __setattr__ desc where to do the cooking
in __getattribute__ __dict__
--
in __getattribute__ name
in __getattribute__ desc
in __getattribute__ __dict__
kitchen (where to do the cooking)
any insight would be much appreciated