5

Say I create a recursive nested list in Python like this:

>>> a = [1,2]
>>> a += [a]

Some properties:

  • len(a) is 3
  • a[2] is a is True

What happens when you print out a? This appears:

>>> a
[1, 2, [...]]

Similarly:

>>> a[2]
[1, 2, [...]]

Why? How does Python "know" the recursion within the list? How is the recursion detected?

hongsy
  • 1,498
  • 1
  • 27
  • 39
  • 4
    Possible duplicate of [What is the ellipsis \[...\] in a Python list?](https://stackoverflow.com/questions/17160162/what-is-the-ellipsis-in-a-python-list) – Yassine Faris May 04 '18 at 08:17
  • I'm not quite sure how it's implemented in Python, but if I were to implement this, when iterating through elements of the list to print, I would check if the element coincides (in the appropriate sense) with the whole list I'm serializing — if so, I would just put ellipses instead of going into a recursive call. – Grisha May 04 '18 at 08:21
  • 1
    @YassineFaris that question is different though, it's not asking how the recursion is detected. – Alex Hall May 04 '18 at 08:22
  • Note that Python 3 also provides a decorator to help make you own repr implementations do this: https://docs.python.org/3/library/reprlib.html#reprlib.recursive_repr – Alex Hall May 04 '18 at 08:23

1 Answers1

11

When Python constructs the repr of a builtin object such as a list it uses two internal functions: Py_ReprEnter(PyObject *), and Py_ReprLeave(PyObject *).

The first of these functions checks we are already handling the repr for the specified object (i.e. looks to see whether it is currently remembering that object). If not it remembers the object and returns 0. In that case the repr code prints the object then calls Py_ReprLeave which removes the object from the set that are currently being tracked.

If Py_ReprEnter is already tracking the object it returns non 0 and in that case the list repr code prints [...].

Duncan
  • 92,073
  • 11
  • 122
  • 156