Home > Mobile >  Is there a way to use __getattr__ as Python classmethod
Is there a way to use __getattr__ as Python classmethod

Time:10-10

getattr works pretty well with instance of class:

class Person:

def __getattr__(self, name):
    print(name)

p = Person()
p.john

Output:

john

but it does not work as classmethod:

class Person:

@classmethod
def __getattr__(cls, name):
    print(name)

Person.john

Output:

AttributeError: type object 'Person' has no attribute 'john'

Is there a way to use getattr for class directly ?

CodePudding user response:

__getattr__, like most special methods, is only looked up on the class of the instance (bypassing the instance itself). Since you're trying to call it on the class itself, it has to be defined on the class that class Person is implementing. By default that's type (the common root for all class types).

If you really need to do this (I suspect an XY problem) you can do this with a metaclass (the class of the class itself):

class PersonMeta(type):
    def __getattr__(cls, name):
        print(cls, name)

class Person(metaclass=PersonMeta):
    def __getattr__(self, name):
        return getattr(type(self), name)  # Delegate to metaclass implementation

Person.john
Person().john

Try it online!

Note that you need to implement a delegating version on the class itself to ensure it delegates back to the metaclass's implementation (assuming you want to be able to have it function on instances of the class, not just on the class itself). The metaclass itself could dynamically attach such a method to the class at construction time (in __prepare__ or __new__) if all instances of the metaclass's classes should exhibit this delegation behavior.

  • Related