I am porting python2 code using old-style classes to python3. The code uses __getattr__
to catch calls to special methods (such as __int__
, __str__
, __hash__
, __repr__
) and delegate these calls to other objects. This is a sample code:
class A():
def __getattr__(self, attr):
return getattr(self.some_method(), attr)
def some_method(self):
return None
class B(A): #in the actual code there are many different subclasses with different some_method implementations
def __init__(self):
self.x = C()
def some_method(self):
return self.x
class C():
def __str__(self):
return "whatever"
def __int__(self):
return 5
b = B()
# in the actual code such calls are happening in indirect ways in different modules
print(int(b)) # 5 in python2, TypeError in python3
In python2 I get result 5
, in python3, as all classes are new-style by default, I get:
TypeError: int() argument must be a string or a number, not 'B'
The question is how to port the code. One way is to define all possible methods (__str__
, __int__
, etc.) in class A. This will be very time consuming as there is no easy way to find all the possible implicit calls to special methods in this specific code.
Is there a way to force __getattr__
or __getattribute__
to intercept special methods (like it was happening with old style classes)? Or is there any other possibility to intercept these calls?
P.S. I have read these to learn that __getattr__
and __getattribute__
do not get called for new-style classes in case the attribute is a special method: