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

Question:

I’m printing a value of a what I thought was a list, but the output that I get is:

[...]

What does this represent? How do I test for it? I’ve tried:

myVar.__repr__() != '[...]'

and

myVar.__repr_() != Ellipsis

but no dice…

Here’s a cutdown of the code that’s giving the issue:

def buildPaths(graph, start, end, path=[], totalPaths=[]):
    """
    returns list of all possible paths from start node to the end node
    """
    path = path + [start]
    if start == end:
        return path
    for nextNode in graph.childrenOf(start):
        if nextNode not in path:
            newPath = buildPaths(graph, nextNode, end, path, totalPaths)
            if newPath != []: # test
                totalPaths.append(newPath)
    return totalPaths

totalPaths contains a LOT of […] supposedly recursive lists, but I can’t see why. I’ve altered the test at #test to prevent this.

I’ve also tried:

def buildPaths(graph, thisNode, end, path=[], totalPaths=None):
    """
   returns list of all possible paths from start node to the end node
   """
    path = path + [thisNode]
    if thisNode == end:
        return path
    for nextNode in graph.childrenOf(thisNode):
        if nextNode not in path:
            newPath = buildPaths(graph, nextNode, end, path, totalPaths)
            if newPath != None:
                if totalPaths == None:
                    totalPaths = [newPath]
                else:
                    totalPaths.append(newPath)
    return totalPaths

in order to explicitly return None for empty paths.

Asked By: Dycey

||

Answers:

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 [...]

Answered By: Nolen Royalty

It’s a recursive reference as your list contains itself. Python doesn’t try to recursively print this which would lead to an infinite loop.

repr detects this. So, if you looked at the internal representation of your list object you would see (where the ellipsis occur) “Reference to the same list object at address *” where * is the address of the original list object in memory. Hence, the infinite loop.

Answered By: Pythonista

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': {...}}
Answered By: mhawke

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']
Answered By: MSeifert