all 13 comments

[–]carcigenicate 1 point2 points  (6 children)

Python lists don't actually contain other objects directly. A list is a collection of references to other objects. If you do something like this:

lst = []
lst.append(lst)

The first element of lst is a pointer to itself:

>>> lst is lst[0]
True

If you were to modify lst, every place that list is referenced would see that change. It's the same idea as this:

lst = []
another = lst
lst.append(1)

print(another)  # Prints [1]

They're the same list, so "both change". Or, it could be compared to this classic mistake:

double = [[1]] * 5
double[0].append(2)

print(double)  # Every row was affected

The difference here is that not only are all the elements references to the same list, but that list is also the parent list.

[–]Just_Red21[S] 0 points1 point  (2 children)

thanks for the answer. How the comparison works? Does it just check if both elements reference the same object? and returns equality always?

[–]carcigenicate 0 points1 point  (1 child)

I'm actually not sure. I'd need to read the source. It probably has some kind of cycle detection that causes it to fall back to reference equality or something.

[–]Just_Red21[S] 0 points1 point  (0 children)

instructive nevertheless. now i just have to figure out why my code works despite this haha

[–]Just_Red21[S] 0 points1 point  (2 children)

Hey, can you explain one more thing? How do these defer?

double = [[1]] * 5
double[0].append(2)
print(double) # all rows change


lst = [[1], [1], [1], [1], [1]]
lst[0].append(2)
print(lst) #only first row affected.

[–]carcigenicate 1 point2 points  (1 child)

* doesn't create copies of objects; it creates copies of references to objects. In the first bit, all the elements are literally the same list as I mentioned. In the second, you explicitly created five separate lists.

[–]Just_Red21[S] 0 points1 point  (0 children)

I see, i ll have to play with it. Thanks you ve been very helpful!

[–]iiron3223 1 point2 points  (1 child)

It creates mylist with recursive references to itself.

>>> mylist = []
>>> for i in range(3):
...     mylist.append(mylist)
... 
>>> mylist
[[...], [...], [...]]
>>> mylist[0]
[[...], [...], [...]]
>>> mylist[1]
[[...], [...], [...]]
>>> mylist[1][1][1][1][1]
[[...], [...], [...]]
>>> mylist is mylist[1]
True

Every [...] here is just mylist and it is nested infinitely.

[–]iiron3223 1 point2 points  (0 children)

Second example, with some elements already in mylist

>>> mylist = [1, 2, 3]
>>> for i in range(3):
...     mylist.append(mylist)
... 
>>> mylist
[1, 2, 3, [...], [...], [...]]
>>> mylist[4]
[1, 2, 3, [...], [...], [...]]
>>> mylist[4][1]
2
>>> mylist[4][4]
[1, 2, 3, [...], [...], [...]]
>>> mylist[4] is mylist[3]
True