print(obj)
invokes str(obj)
(to get a printable representation), which in turn tries to invokes obj.__str__()
(and fallback to something else if this fails, but that's not the point here).
You defined Lz
as an old-style class, so it's doesn't by default have a __str__
method (new-style classes inherit this from object
), but you defined a __getattr__()
method, so this is what gets invoked in the end (__getattr__()
is the last thing the attribute lookup will invoke when everything else has failed).
NB: in case you don't already know, since everything in Python is an object - include classes, functions, methods etc - Python doesn't make difference between "data" attributes and "method" attributes - those are all attributes, period.
NB2: directly accessing __magic__
names is considered bad practice. Those names are implementation support for operators or operator-like generic functions (ie len()
, type
etc), and you are supposed to use the operator or generic function instead. IOW, this:
return self.b.__getattribute__(item)
should be written as
return getattr(self.b, item)
(getattr()
is the generic function version of the "dot" attribute lookup operator (.
))