Though I could not find the source code, based on the results I posted in my question it is very likely that __str__
and __repr__
for float
are implemented along the lines:
class float:
def __repr__(self):
return ??? # core implementation, maybe from C???
def __str__(self):
return self.__repr__() # falls back to __repr__()
This logic explains all four cases. For example, in case 2b, calling repr(storage)
calls Storage.__repr__(storage)
, which then calls float.__str__(storage)
, which falls back to float.__repr__(storage)
, which is finally resolved to Storage.__repr__(storage)
(because of the method override and OOP). The loop closes and goes into an infinite recursion, or at least up until the max depth is reached and we get a RecursionError: maximum recursion depth exceeded while calling a Python object