Py学习  »  Python

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

Vivek Gani • 6 年前 • 2294 次点击  

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 ,没有任何引用的正确实例化方法如下:

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 ,是否有方法检查数组,使其显示正在使用引用?仅仅打印数组不会显示引用。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/43486
文章 [ 2 ]  |  最新文章 6 年前
iz_
Reply   •   1 楼
iz_    7 年前

你可以使用 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 ,它们是不同的。

timgeb
Reply   •   2 楼
timgeb    7 年前

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

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

>>> 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 长度列表中对象的唯一ID n .

如果您的列表包含大量元素,那么惰性地执行此操作并返回 False 在第一个重复的id上。

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