О присваивании с использованием среза списка с рекурсивной ссылкой на его копию

В исходниках functools.lru_cache можно встретить следующий кусочек кода:

root = []  # root of the circular doubly linked list
root[:] = [root, root, None, None]  # initialize by pointing to self

Что происходит в этой ситуации? Есть ли какой-то другой синтаксис для достижения того же результата?

В выражении

root[:] = [root, root, None, None]

Присваивание среза в левой части говорит о том, что ссылка на переменную root используется повторно для хранения содержимого правой части выражения.

Таким образом, ссылка на root никогда не меняется. И в списке можно ссылаться на себя. Только не стоит пытаться с помощью рекурсии получить плоский список. :-)

Посмотрите на формальное строковое представление. «Рекурсия по списку» отлично видна:

>>> root
[<Recursion on list with id=48987464>,
 <Recursion on list with id=48987464>,
 None,
 None]

Попробуйте распечатать root — увидите эллипсис:

>>> print(root)
[[...], [...], None, None]

Для достижения такого же результата необязательно использовать срез. Рекурсии можно добиться так:

>>> root = []
>>> root.append(root)
>>> root
[<Recursion on list with id=51459656>]
>>> 

Метод append() не меняет ссылку — меняется список путем добавления ссылки на себя.

Такой вариант может быть более простым для понимания.


Спасибо Jean-François Fabre.