What is happening when I assign a list with self references to a list copy with the slice syntax `mylist[:] = [mylist, mylist, …]`?

  • A+

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.


  1. What is going on in this situation.
  2. Is there a different syntax to achieve the same result?
  3. Is there a different common use case for some_list[:] = some_iterable (without the self reference)?



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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: