Python-如何检查/发现列表中有引用?

时间:2018-12-08 22:16:07

标签: python list reference

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

问题是这样的-假设确实像列表a一样定义了它们的列表,有没有办法检查数组以表明它正在使用引用?仅打印阵列将不会显示引用。

2 个答案:

答案 0 :(得分: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 :(得分: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