I'm working on a project right now that deals with functions in an abstract mathematical sense. Without boring the reader with the details, I'll say that I had the following structure in an earlier version:
class Foo(Bar):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.sub_unit = Foo(a, not b)
Of course, that's not quite the change I'm making to the arguments to Foo, but suffice to say, it is necessary that this property, if accessed repeatedly, result in an indefinitely long chain of Foo objects. Obviously, this results in an infinite recursion when one instantiates Foo. I solved this in the earlier version by removing the last line of init and adding the following to the Foo class:
def __getattr__(self, attr: str):
    if attr == 'sub_unit':
        return Foo(self.a, not self.b)
    else:
        return super().__getattr__(attr)
This worked quite well, as I could calculate the next object in the chain as needed.
In going over the code, though, I realize that for other reasons, I need an instance of Bar, not a sub-class of it. To see if I could override the getattr for a single instance, I tried the following:
>>> foo = Bar(a=1, b=2) # sub_unit doesn't get set here.
>>> foo.__getattr__ = lambda attr: 'foo'
>>> foo.a
1
>>> foo.__getattr__('a')
'foo'
What is happening here that I don't understand? Why isn't foo.a calling foo.__getattr__('a')?
Is there a good way to overwrite __getattr__ for a single instance, or is my best bet to re-factor all the code I have that reads sub_unit and friends to call those as functions, to handle this special case?