I was just looking at the implementation of functools.lru_cache, when I stumbled across this snippet:
root = [] # root of the circular doubly linked list
root[:] = [root, root, None, None] # initialize by pointing to self
I am familiar with circular and doubly linked lists. I am also aware that new_list = my_list[:]
creates a copy of my_list.
When looking for slice assignments or other implementations of circular doubly linked lists, I could not find any further information on this specific syntax.
Questions:
some_list[:] =
some_iterable
(without the self reference)?in
root[:] = [root, root, None, None]
left hand slice assignment just says that the reference of root
is reused to hold the contents of the right part.
So root
reference never changes, and yes, in a list you can reference yourself (but don't try recursive flattening on those :). The representation displays a "recursion on list" in that case.
>>> root
[<Recursion on list with id=48987464>,
<Recursion on list with id=48987464>,
None,
None]
and printing it shows ellipsis:
>>> print(root)
[[...], [...], None, None]
note that you don't need slice assignment for this. There are simple ways to trigger a recursion:
>>> root = []
>>> root.append(root)
>>> root
[<Recursion on list with id=51459656>]
>>>
using append
doesn't change reference as we all know, it just mutates the list, adding a reference to itself. Maybe easier to comprehend.