【问题标题】:Python - how to inspect / discover list has references?Python - 如何检查/发现列表有引用?
【发布时间】:2018-12-08 22:16:06
【问题描述】:

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,有没有一种方法可以检查数组以显示它正在使用引用?仅仅打印数组不会显示引用。

【问题讨论】:

  • 在这两种情况下都使用引用。对于 CPython,有 sys.getrefcount() 可能表示有多少引用指向一个对象
  • python中的所有对象都有一个地址。

标签: python list reference


【解决方案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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 2013-12-15
      • 2011-06-26
      相关资源
      最近更新 更多