pythonclass-methodgetattr

__getattr__ for static/class variables


I have a class like:

class MyClass:
     Foo = 1
     Bar = 2

Whenever MyClass.Foo or MyClass.Bar is invoked, I need a custom method to be invoked before the value is returned. Is it possible in Python? I know it is possible if I create an instance of the class and I can define my own __getattr__ method. But my scnenario involves using this class as such without creating any instance of it.

Also I need a custom __str__ method to be invoked when str(MyClass.Foo) is invoked. Does Python provide such an option?


Solution

  • __getattr__() and __str__() for an object are found on its class, so if you want to customize those things for a class, you need the class-of-a-class. A metaclass.

    class FooType(type):
        def _foo_func(cls):
            return 'foo!'
    
        def _bar_func(cls):
            return 'bar!'
    
        def __getattr__(cls, key):
            if key == 'Foo':
                return cls._foo_func()
            elif key == 'Bar':
                return cls._bar_func()
            raise AttributeError(key)
    
        def __str__(cls):
            return 'custom str for %s' % (cls.__name__,)
    
    class MyClass(metaclass=FooType):
        pass
    
    # # in python 2:
    # class MyClass:
    #    __metaclass__ = FooType
    
    
    print(MyClass.Foo)
    print(MyClass.Bar)
    print(str(MyClass))
    

    printing:

    foo!
    bar!
    custom str for MyClass
    

    And no, an object can't intercept a request for a stringifying one of its attributes. The object returned for the attribute must define its own __str__() behavior.

    Updated 2023-02-20 for Python 3.x default implementation (python 2 as a comment).