【问题标题】:What does Python mean by printing "[...]" for an object reference?Python 为对象引用打印“[...]”是什么意思?
【发布时间】:2016-08-22 14:36:38
【问题描述】:

我正在打印一个我认为是列表的值,但我得到的输出是:

[...]

这代表什么?我该如何测试它?我试过了:

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

myVar.__repr_() != Ellipsis

但没有骰子...

这是导致问题的代码的删减:

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 包含很多 [...] 所谓的递归列表,但我不明白为什么。我已经更改了 #test 的测试以防止这种情况发生。

我也试过了:

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

为了为空路径显式返回None

【问题讨论】:

  • 虽然Ellipsis 是python 中的一个东西,但这可能只是告诉你有比它所能显示的更多的东西的任何显示。 >>> [...] -> [Ellipsis](从 python3 开始)
  • 您能否提供一个生成此代码的示例?
  • @BrenBarn - 添加示例代码
  • 当你做totalPaths.append(newPath)时,那是在修改传入的列表,所以父递归的totalPaths也被修改了——然后作为newPath返回并附加到自身。
  • 谢谢@Izkata - 这就是我要找的解释!

标签: python recursion ellipsis recursive-datastructures


【解决方案1】:

根据这里的上下文,它可能会有所不同:

使用Ellipsis 进行索引/切片

我认为它没有为任何 python 类实现,但它应该代表任意数量的数据结构嵌套(根据需要)。 例如:a[..., 1] 应该返回最内层嵌套结构的所有第二个元素:

>>> 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]])

要检查这个...,请将其与Ellipsis 进行比较(这是一个单例,因此建议使用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

递归数据结构

您在您的输出 中看到[...] 的另一种情况是,如果您在序列本身中有序列。这里它代表一个 infinite 深度嵌套的序列(不可打印)。例如:

>>> 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'

你甚至可以多次替换它:

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

要测试您的输出中是否有任何此类递归,您需要检查数据结构本身是否也是元素之一:

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

获得更有意义的输出的另一种方法是使用pprint.pprint

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

【讨论】:

    【解决方案2】:

    如果您的列表包含自引用,Python 会将其显示为[...],而不是尝试递归打印它,这将导致无限循环:

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

    无限。

    字典也会出现类似的情况:

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

    【讨论】:

      【解决方案3】:

      这是一个递归引用,因为您的列表包含自身。 Python 不会尝试递归打印这会导致无限循环。

      repr 检测到这一点。因此,如果您查看列表对象的内部表示,您会看到(省略号出现的位置)“引用地址 * 处的相同列表对象”,其中 * 是内存中原始列表对象的地址。因此,无限循环。

      【讨论】:

        【解决方案4】:

        它代表结构内的无限循环。一个例子:

        In [1]: l = [1, 2]
        
        In [2]: l[0] = l
        
        In [3]: l
        Out[3]: [[...], 2]
        

        l 的第一项就是它自己。这是一个递归引用,因此 python 无法合理地显示其内容。相反,它显示[...]

        【讨论】:

        • 好吧,如果它被延迟计算,它可以显示结果。 GHCi 显示无限列表没有问题。
        • @Carcigenicate 实际上,GHCi 开始显示无限列表没有问题,但它很难完成...... Python 有点需要 repr 在打印之前完成执行。
        • Common Lisp 有一个用于打印“循环”列表结构的特殊符号,请参阅stackoverflow.com/questions/16678371/…
        猜你喜欢
        • 2012-08-15
        • 2011-06-12
        相关资源
        最近更新 更多