首页 文章

Python - 如何检查/发现列表有参考?

提问于
浏览
1

python中更令人困惑的一个方面是实例化一个列表列表(假设一个没有使用numpy) - 例如,如果一个人试图通过简单的乘法来完成它,你最终得到了引用副本:

In [1]: a = [[0] * 4] * 4
In [2]: a
Out[2]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

In [3]: a[0][1] = 1
In [4]: a
Out[4]: [[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

正如在this one等各种其他SO帖子中所提到的,在没有任何引用的情况下实例化的正确方法如下:

In [5]: b = [[0 for i in range(4)] for i in range(4)]
In [6]: b         
Out[6]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

In [7]: b[0][1] = 1
In [8]: b                                           
Out[8]: [[0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

问题是这个 - 假设一个人确实用list a 定义了他们的列表,有没有办法以这样的方式检查数组,它会显示它正在使用引用?仅打印阵列不会显示参考 .

2 回答

  • 1

    您可以使用 id 函数:

    >>> a = [[0] * 4] * 4
    >>> a
    [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    >>> [id(sublist) for sublist in a]
    [1975671202696, 1975671202696, 1975671202696, 1975671202696]
    >>> b = [[0 for i in range(4)] for i in range(4)]
    >>> b
    [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    >>> [id(sublist) for sublist in b]
    [1975671204808, 1975671205128, 1975671205000, 1975671204872]
    

    正如您所看到的,在 a 中,ID都是相同的,而在 b 中,它们是不同的 .

  • 1

    首先是一些术语:你在这里谈论列表(不是数组),它总是存储对其元素的引用 .

    检查列表中的所有引用是否引用不同对象的快速方法是

    >>> l1 = [[0, 1], [0, 1]]
    >>> l2 = [[0, 1]]*2
    >>> 
    >>> len(set(map(id, l1))) == len(l1) # no duplicates
    True
    >>> len(set(map(id, l2))) == len(l2) # duplicates
    False
    

    它只是检查长度为 n 的列表中的对象是否有 n 唯一ID .

    如果您的列表中包含大量元素,那么懒惰地执行此操作可能会更有效,并在第一个重复ID上返回 False .

    def all_unique(lst):
        seen = set()
        for x in lst:
            id_ = id(x)
            if id_ in seen:
                return False
            seen.add(id_)
        return True
    

    ......这样工作:

    >>> all_unique(l1)
    True
    >>> all_unique(l2)
    False
    

相关问题