Home > front end >  Which magic methods are called when getting a class variable in Python?
Which magic methods are called when getting a class variable in Python?

Time:11-03

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
  • Related