I am trying to wrap my head around how __getattribute__
and __getattr__
work in Python with respect to uninstantiated classes and subclassing. Specifically I want to capture a getattribute
call in the super class and potentially modify it accordingly.
In the following code snippet, I would have expected at least some intermediate print statements when any of the methods are called, but I am not getting anything. The class variable is found and returned but seemingly none of the magic methods are called. Why is that?
class SuperbClass:
def __getattribute__(self, attr):
print(f"called in superb, found {attr}")
# get the attribute via `object`
return f"{super(SuperbClass, self).__getattribute__(attr)}MODIFIED_IN_SUPER"
def __getattr__(self, attr):
self.__getattribute__(attr)
class SubberClass(SuperbClass):
MyClassVar = "I am a cool message"
def __getattribute__(self, attr):
print("called in subber")
super(SuperbClass, self).__getattribute__(attr)
def __getattr__(self, attr):
self.__getattribute__(attr)
if __name__ == '__main__':
print(SubberClass.MyClassVar)
# Only prints `I am a cool message`
inst = SubberClass()
print(inst.MyClassVar)
# prints called in subber
# and prints None
EDIT: updated code to reflect the difference between class and instance
CodePudding user response:
A class's __getattribute__
and __getattr__
handle attribute resolution for instances of the class. If you want to handle attribute resolution for the class itself, you need to define __getattribute__
or __getattr__
on the class's class: its metaclass.
class Meta(type):
def __getattribute__(self, attr):
print('*This* prints.')
return super().__getattribute__(attr)
class Blah(metaclass=Meta):
MyClassVar = 'blah'
if __name__ == '__main__':
Blah.MyClassVar