Python基本数据引用,列表相同的引用

daw*_*awg 7 python reference data-structures

说我有两个清单:

>>> l1=[1,2,3,4]
>>> l2=[11,12,13,14]
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

由于它们是引用,我可以更改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]}
Run Code Online (Sandbox Code Playgroud)

包括如果我在字典中添加引用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]
Run Code Online (Sandbox Code Playgroud)

如果我现在设置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
Run Code Online (Sandbox Code Playgroud)

并且附加或改变l1不会改变,d['l1']或者t[0]因为它现在是一个新的参考.间接引用的概念在Python文档中得到了很好的介绍,但并不完全.

我的问题:

  1. 可变对象总是引用吗?你能不能一直认为修改它会修改原件(除非你专门用l2=l1[:]一种成语制作副本)?

  2. 我可以在Python中汇编所有相同引用的列表吗?ie,如果所有那些引用相同的列表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
Run Code Online (Sandbox Code Playgroud)

aar*_*ing 6

1)通过引用修改可变对象将始终修改"原始".老实说,这背叛了对参考文献的误解.较新的引用与任何其他引用一样多.只要两个名称都指向同一个对象,通过其他名称访问时,将反映通过任一名称修改对象.

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
Run Code Online (Sandbox Code Playgroud)

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

3)如果有效,你的意思是"不会被垃圾收集"那么这是正确的,除非是一个非常不可能的错误.这将是一个非常抱歉的垃圾收集器"窃取"您的数据.