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?