0

Can a list be put inside the same list in python? What is the purpose of this?

>>> a = [2, 5, 2]
>>> a.extend([a])
>>> a
[2, 5, 2, [...]]
>>> print(a[3])
[2, 5, 2, [...]]
>>> print(a[1])
5
>>> print(a[2])
2
>>> print(a[3])
[2, 5, 2, [...]]
>>> print(a[4])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> print(a[3])
[2, 5, 2, [...]]
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
Majoris
  • 2,963
  • 6
  • 47
  • 81
  • 4
    Um, yes? Your code seems to demonstrate this pretty clearly. What exactly are you asking? Note, `a.extend([a])` is a weird way of writing `a.append(a)`. As an aside, please always use the generic [python] tag for all python related questions – juanpa.arrivillaga Nov 11 '19 at 22:51
  • You append a reference to the list inside itself, making it an infinitely recursing structure. You usually never need this. What is your question? – cs95 Nov 11 '19 at 22:52
  • how something can be put inside itself? – Majoris Nov 11 '19 at 22:53
  • 4
    Not everything that can be done has a purpose. I can put a banana on my head. What is the purpose of this? – user2357112 Nov 11 '19 at 22:54
  • 1
    @KapishM It can be done because Python uses references. It's like a C structure that has a pointer to itself. – Barmar Nov 11 '19 at 22:55
  • Then what happens to the one inside list when I alter it. – Majoris Nov 11 '19 at 22:56
  • What do you mean *"how"*? Syntactically, what you've posted already shows how you can write code to do that. In terms of implementation, a CPython list is an array of references, so the fact that one of those references is to the array is fine. – jonrsharpe Nov 11 '19 at 22:57
  • 1
    it modifies the original list as well, since they're the same list. – Barmar Nov 11 '19 at 22:57
  • 1
    I think the reason it is not forbidden is because there is no good reason to forbid it (just allowing recursive lists is easier to implement than checking for recursion every time you mutate a list). – wim Nov 11 '19 at 22:57
  • @jonrsharpe well, the reference itself is a pointer to the PyObject header, the Python object itself has a pointer to a primitive array of PyObject pointers... – juanpa.arrivillaga Nov 11 '19 at 22:59
  • Possible duplicate of https://stackoverflow.com/questions/24354645/what-happens-if-you-append-a-list-to-itself – cs95 Nov 11 '19 at 23:01

1 Answers1

4

Yes, as your own code shows, it is possible for a list to contain itself as a member. Strictly speaking the list contains a reference to itself. Think of it like a book which has its own title written on one of its pages; the book doesn't really contain itself, just a reference to itself, so there is no paradox.

As for the purpose, there is rarely a reason to do this; but there is also no good reason for the language to prevent you from doing it. However, more indirect recursive references can be very useful. Consider the adjacency list data structure for a graph:

class Node:
    def __init__(self, name):
        self.name = name
        self.neighbours = []

# the graph has two nodes
node_a = Node('a')
node_b = Node('b')

# they are neighbours of each other
node_a.neighbours.append(node_b)
node_b.neighbours.append(node_a)

Now node_a.neighbours[0].neighbours is a list which contains node_a - a recursive self-reference.

kaya3
  • 47,440
  • 4
  • 68
  • 97
  • 2
    And there is good reason for the language *not* to prevent you from doing it. Checking for self-referential lists would mean either `O(n)` time or `O(n)` space for an append. – wim Nov 11 '19 at 22:58
  • 1
    Indeed, and even worse if you want to forbid indirect self-reference too. – kaya3 Nov 11 '19 at 22:59
  • Actually, thinking about it, forbidding direct self-reference would only need `if x is self: raise ValueError()` in a few list methods, which would be O(1). – kaya3 Nov 11 '19 at 23:12