Python基础资料引用,相同引用列表

标签 python data-structures reference

假设我有两个列表:

>>> l1=[1,2,3,4]
>>> l2=[11,12,13,14]

我可以将这些列表放入元组或字典中,看起来它们都是对原始列表的引用:

>>> t=(l1,l2)
>>> d={'l1':l1, 'l2':l2}
>>> id(l1)==id(d['l1'])==id(t[0])
True
>>> l1 is d['l1'] is t[0]
True

因为它们是引用,我可以更改 l1 并且元组和字典中引用的数据会相应地更改:

>>> l1.append(5)
>>> l1
[1, 2, 3, 4, 5]
>>> t
([1, 2, 3, 4, 5], [11, 12, 13, 14])
>>> d
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5]}

包括如果我在字典 d 中附加引用或在元组 t 中附加可变引用:

>>> d['l1'].append(6)
>>> t[0].append(7)
>>> d
{'l2': [11, 12, 13, 14], 'l1': [1, 2, 3, 4, 5, 6, 7]}
>>> l1
[1, 2, 3, 4, 5, 6, 7]

如果我现在将 l1 设置为一个新列表,原始列表的引用计数会减少:

>>> sys.getrefcount(l1)
4
>>> sys.getrefcount(t[0])
4
>>> l1=['new','list']
>>> l1 is d['l1'] is t[0]
False
>>> sys.getrefcount(l1)
2
>>> sys.getrefcount(t[0])
3

并且附加或更改 l1 不会更改 d['l1']t[0],因为它现在是一个新引用。间接引用的概念是 covered fairly well在 Python 文档中,但不完全。

我的问题:

  1. 可变对象总是是引用吗?您是否可以总是假设修改它会修改原始文件(除非您特别使用 l2=l1[:] 那种习语制作副本)?

  2. 我可以在 Python 中汇总所有相同引用的列表吗?即,某些函数 f(l1) 返回 ['l1', 'd', 't'] 如果所有这些都引用同一个列表?

  3. 我的假设是,无论如何,只要有人引用数据,数据就会一直有效。

即:

l=[1,2,3]         # create an object of three integers and create a ref to it
l2=l              # create a reference to the same object
l=[4,5,6]         # create a new object of 3 ints; the original now referenced 
                  # by l2 is unchanged and unmoved

最佳答案

1) 通过引用修改可变对象将总是修改“原始对象”。老实说,这是对引用的误解。较新的引用与任何其他引用一样都是“原始”。只要两个名称都指向同一个对象,通过另一个名称修改对象将反射(reflect)在通过另一个名称访问时。

2) 与您想要的不完全一样。 gc.get_referrers 返回对该对象的所有 引用。

>>> l = [1, 2]
>>> d = {0: l}
>>> t = (l, )
>>> import gc
>>> import pprint
>>> pprint.pprint(gc.get_referrers(l))
[{'__builtins__': <module '__builtin__' (built-in)>,
  '__doc__': None,
  '__name__': '__main__',
  '__package__': None,
  'd': {0: [1, 2]},
  'gc': <module 'gc' (built-in)>,
  'l': [1, 2],
  'pprint': <module 'pprint' from '/usr/lib/python2.6/pprint.pyc'>,
  't': ([1, 2],)},   # This is globals()

 {0: [1, 2]},  # This is d
 ([1, 2],)]   # this is t

请注意,l 引用的实际对象不包含在返回的列表中,因为它不包含对自身的引用。 globals() 被返回,因为它确实包含对原始列表的引用。

3) 如果有效是指“不会被垃圾收集”,那么这是正确的,除非出现极不可能的错误。如果垃圾收集器“窃取”了您的数据,那就太遗憾了。

关于Python基础资料引用,相同引用列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4557223/

相关文章:

python - 将列表中的类对象添加到 QWidget

Python GC 计数器 - Rosalind

c++ - 如何在左子右兄弟树中找到节点的父节点?

php - 如何传递对 call_user_func 的引用?

c++ - 分配对结构的引用

python - 如何正确测试程序 python 脚本

python - 无法通过 sh/crontab 启动 python 程序

java - 尝试使用两个 if 语句打印树的顶 View

data-structures - 在 Haskell 中递归修改部分数据结构

c++ - 将对象引用转换为 STL 迭代器