This MWE in the past would cause a stack overflow, as x references y that references x:
class Ref:
def __init__(self, name):
self.name = name
self.value = None
def __repr__(self):
if self.value is None:
return self.name
return f"{self.name}={self.value!r}"
if __name__ == '__main__':
x, y = Ref("x"), Ref("y")
x.value = (1, y)
y.value = (2, x)
print(x)
print(y)
But as I test it with CPython 3.10.4, it works out of the box!
x=(1, y=(2, x=(...)))
y=(2, x=(1, y=(...)))
I can't find when this behavior changed. I see several questions as recent as 2020 wondering how to handle mutually- or self-recursive data structures. I also found about the reprlib builtin library which produces similar output, so I suspect some language dev decided to use it by default.
Note: I also tested it with __str__ and it also works, so it's not specific to repr().
It actually never really did, and still doesn't as of today (version 3.12.0 alpha 0).
The case you show is the simplest possible one: recursive
reprwith instances of the same class. In such case, it's pretty easy for the interpreter to detect that therepris going to cause infinite recursion and therefore stop and produce...instead: it just needs to check whether the.__repr__()method for the current class is asking for the.__repr__()of an instance of the same class.This has been supported since Python 1.5.1 (1998!) as can be seen in
Misc/HISTORY:Any slightly more complex case will still cause trouble even on the latest CPython version: