There are two potential problems.
First, you rely on your __getattribute__ implementation to have the interpreter find the correct __add__ method. Unfortunately, I noticed that the Python interpreter often has problems finding special functions, such as __add__ or __call__ , if they are created on the fly (that is, they do not form an explicit part of the class when defining the class). The guides clearly confirm this, at least for new-style classes:
For classes of a new style, implied calls for special methods are only guaranteed to work correctly if determined by the type of objects, and not in the dictionary instance of objects.
although it seems to me that I had problems with similar tricks even with old-style classes.
Secondly, simply redirecting __add__ will not be enough. Even if the interpreter successfully reduces
a + b
to
float.__add__( 1.22, b )
class float still does not know how to add float to ref . So your __add__ should explicitly dereference the target (and dereference it if it is an indirect reference (and dereference it ...). Thus:
class ref: def __init__(self, obj): self.obj = obj def get(self): return self.obj def set(self, obj): self.obj = obj def __str__(self): return self.obj.__str__() def __add__( self, other ): while isinstance( other, ref ): other = other.obj return self.obj.__add__( other ) a = ref(1.22) b = ref(a) print a print b print a + b
The while in __add__ ensures that you completely unpacked all nested references to the base object.
If I did this and I used similar constructions to implement proxy templates, I would reorganize the while loop in its own method, say getBaseObject (), and then it is called every time we need an object, i.e. on The actual basis of the link chain.