The dunder method __getattr__(self, name) is called when a user of an object tries to access a member or method that does not exist. In such a case, the name of the inexistant member/method is passed to __getattr__(self, name).
In the following example, the classCls defines __getattr__. When it is called, it creates an instance of a Cls.notAvailableMember object. If the inexesting member was called in «property context», the member method __str__ of notAvailableMember is called. If the inexisting member was called in «method context», the __call__ method is called.
class Cls:
class notAvailableMember:
def __init__(self, txt):
self.txt = txt
def __str__(self):
return self.txt + ', which is unimplemented, was accessed as a member property'
def __call__(self):
print(self.txt + ', which is unimplemented, was called as a method')
def __init__(self):
self.member_one = 'first member'
self.member_two = 'second member'
def __getattr__(self, name):
print('C.__getattr__ with name = ' + name + ' was called')
return Cls.notAvailableMember(name)
def method_one(self):
print('method_one was called')
c = Cls()
print(str(c.member_one ))
#
# first member
print(str(c.member_two ))
#
# second member
print(str(c.member_three))
#
# C.__getattr__ with name = member_three was called
# member_three, which is unimplemented, was accessed as a member property
c.method_one()
#
# method_one was called
c.method_two()
#
# C.__getattr__ with name = method_two was called
# method_two, which is unimplemented, was called as a method