What does Python mean by printing "[...]" for an object reference?

It represents an infinite loop within the structure. An example:

In [1]: l = [1, 2]

In [2]: l[0] = l

In [3]: l
Out[3]: [[...], 2]

l's first item is itself. It's a recursive reference, and so python can't reasonably display its contents. Instead it shows [...]


Depending on the context here it could different things:

indexing/slicing with Ellipsis

I think it's not implemented for any python class but it should represent an arbitary number of data structure nestings (as much needed). So for example: a[..., 1] should return all the second elements of the innermost nested structure:

>>> import numpy as np
>>> a = np.arange(27).reshape(3,3,3)  # 3dimensional array
>>> a[..., 1]  # this returns a slice through the array in the third dimension
array([[ 1,  4,  7],
       [10, 13, 16],
       [19, 22, 25]])
>>> a[0, ...]  # This returns a slice through the first dimension
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

and to check for this ... you compare it to an Ellipsis (this is a singleton so recommended is using is:

>>> ... is Ellipsis
True
>>> Ellipsis in [...]
True
# Another (more or less) equivalent alternative to the previous line:
>>> any(i is Ellipsis for i in [1, ..., 2]) 
True

Recursive Datastructures

The other case in which you see an [...] in your output is if you have the sequence inside the sequence itself. Here it stands for an infinite deeply nested sequence (that's not printable). For example:

>>> alist = ['a', 'b', 'c']
>>> alist[0] = alist
>>> alist
[[...], 'b', 'c']

# Infinite deeply nested so you can use as many leading [0] as you want
>>> alist[0][1] 
'b'
>>> alist[0][0][0][0][0][1] 
'b'
>>> alist[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][1] 
'b'

You can even replace it several times:

>>> alist[2] = alist
>>> alist
[[...], 'b', [...]]
>>> alist[1] = alist
>>> alist
[[...], [...], [...]]

To test if you have any such recursion in your output you need to check if the data-structure itself is also one of the elements:

>>> alist in alist
True
>>> any(i is alist for i in alist)
True

Another way to get a more meaningful output is using pprint.pprint:

>>> import pprint
>>> pprint.pprint(alist)  # Assuming you only replaced the first element:
[<Recursion on list with id=1628861250120>, 'b', 'c']

If your list contains self references Python will display that as [...] rather than trying to recursively print it out, which would lead to an infinte loop:

>>> l = [1, 2, 3]
>>> print(l)
[1, 2, 3]
>>> l.append(l)
>>> print(l)
[1, 2, 3, [...]]
>>> print(l[-1])        # print the last item of list l
[1, 2, 3, [...]]
>>> print(l[-1][-1])    # print the last item of the last item of list l
[1, 2, 3, [...]]

ad infinitum.

A similar situation arises with dictionaries:

>>> d = {}
>>> d['key'] = d
>>> print(d)
{'key': {...}}
>>> d['key']
{'key': {...}}
>>> d['key']['key']
{'key': {...}}