I want to add some logging to __getattr__
method in python classic class. It work well normally, but when using operator overloading, something was wrong.
My code follows:
class A:
def __getattr__(self, item):
print('attr:'+ item)
def __getattribute__(self, item):
print('attribute:' + item)
return object.__getattribute__(self, item)
def __add__(self, other):
return 2
b = A()
a = b + 1
print(a)
in the line a = b + 1
, it will run the __getattr__
method, and the value of item
will be __coerce__
. In this case, I don't know how to handle it.
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__
).