The trouble you have is that your __getattr__
method is returning None
. Since that's a valid attribute value, Python doesn't know that this is just the default return value from a function that doesn't have a return
statement.
If you don't have anything to return from __getattr__
, you should probably raise an AttributeError
rather than returning None
by default. In this specific situation, Python is checking for a __coerce__
method. If there is an AttributeError
, it will be suppressed and the interpreter will fall back on other behavior (using __add__
). Try something like this:
def __getattr__(self, item):
print('attr:', item)
raise AttributeError("%s object has no attribute named %r" %
(self.__class__.__name__, item))
Now, Python's automatic lookup for __coerce__
will fail, but because it fails in the expected way, the exception will be ignored and the __add__
method will be called as you expect.
One final thing: Old-style classes in Python are thoroughly obsolete (and have been removed from Python 3). You should not use them unless you need to maintain compatibility in very old software that ran on Python versions prior to 2.2 (which was released more than 12 years ago in 2001, so this compatibility issue is becoming a bit ridiculous). For new code that does not have to work with such ancient Python versions, you should use new-style classes everywhere. Because you're using an old-style class, your __getattribute__
method will never be called (only __getattr__
).