14

If I run the following code

data = [[1,2],[3,4],[5,6]]

for x in data:
    print(x[0])

for x[0] in data:
    print(x)

I get the following output

1
3
5
[[1, 2], 6]
[[3, 4], 6]
[[...], 6]

I end up with a list containing [[...], 6], but what is this [...] list?

It doesn't behave normally, because calling y = [[...], 6] and then the following statements show [...] to be 0

>>> print(y)
[[Ellipsis], 6]

>>> print(y[0])
[0]

However when I run the code at the top, and type the following statements the results don't make sense:

>>> print(x)
[[...], 6]

>>> print(x[0])
[[...], 6]

>>> print(x[0][0])
[[...], 6]

>>> print(x[0][0][0])
[[...], 6]

and yet somehow both of these result in 6

>>> print(x[1])
6

>>> print(x[0][1])
6

To review the question: How is this possible, and what does [...] represent, and how can the for loop at the top create such a list?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Rlz
  • 1,649
  • 2
  • 13
  • 36
  • 3
    Did you do any research? https://stackoverflow.com/questions/17160162/what-do-ellipsis-mean-in-a-list – jonrsharpe Jan 06 '19 at 15:34
  • Strangely I couldn't find that question from my searches, it seems to answer the question perfectly. The only question that remains unanswered is how does the for loop create such a list? @jonrsharpe – Rlz Jan 06 '19 at 15:37
  • Because each step of the loop assigns the next element from `x` to `x[0]`. Those two loops are **not** the same. – jonrsharpe Jan 06 '19 at 15:38

2 Answers2

11

Let's give your sublists names:

a = [1, 2]
b = [3, 4]
c = [5, 6]
data = [a, b, c]

Your first loop binds a, b and c successively to x. When the loop terminates, you have effectively set x = c.

The second loop now binds a, b and c successively to x[0]. This is fine for a and b, but for c you are effectively doing c[0] = c, creating a circular reference. Since list is able to catch that, it won't try to print [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[...

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
5

that's because you're using x[0] as your loop variable (which is bad practice) which exists as a list and not a new name like you're supposed to when iterating with for

for x[0] in data:
    print(x)

and x is in data so there's a cyclic reference (hence the ellipsis representation to avoid infinite recursion when printing the same data over and over)

More in detail:

The ellipsis happens on the last element because of the previous loop that binds x on the last element of data ([5,6]).

So the second loop assigns [5,6] to x[0] but it's also x. On way to get rid of this is to create a copy of x just before the second loop: x = x[:]

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219