python:可变对象的id() - 解释有趣的模式?

时间:2015-12-30 09:03:15

标签: python memory implementation

当调用具有相等值的可变对象的标识时,会出现以下模式。 如您所见,id(mutObj)返回的值并不完全独立于id(mutObj)的先前返回值,但模式不稳定。

这种行为对于Python代码本身来说可能是无关紧要的,但是我对了解底层机制非常感兴趣!

>>> id([1,2])
6706248
>>> id([1,2])
59597256
>>> id([1,2])
56866632
>>> id([1,2])
56866632
>>> id([1,2])
56881992
>>> id([1,2])
56881992
>>> id([1,2])
56879624
>>> id([1,2])
56867784
>>> id([1,2])
56867784
>>> id([1,2])
56879624
在win32上

Python 3.4.3 [MSC v.1600 64位(AMD64)]

请注意,最后一个值等于之前返回的三个调用值。

2 个答案:

答案 0 :(得分:1)

立即重新使用id

Python对您创建的所有对象使用相同的id

>>> for x in range(10):
        print(id([1, 2]))
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736
4479841736

由于没有对创建列表的引用,因此将立即对其进行垃圾回收,并重新使用id

重复使用相同的名称

将列表分配给名称obj,将使列表保持活动状态,直到将新列表分配给同一名称:

>>> for x in range(10):
        obj = [1, 2]
        print(id(obj))
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192
4486925128
4486925192

在第二次迭代中,obj存在且obj = [1, 2]在分配给obj之前先创建新列表。分配后,旧列表将被垃圾收集,id再次可用以重复使用。每次迭代都重复此操作。

保留参考

当您将列表中的引用保留到所有创建的列表时:

>>> objs = []
>>> for x in range(10):
        obj = [1, 2]
        print(id(obj))
        objs.append(obj)
4480011848
4483963144
4486916488
4486914376
4486914568
4486916616
4486914824
4486915016
4486915272
4486915464

Python必须为所有这些使用不同的id

口译员效果

在标准的交互式提示符(Python 3.5.1)中工作,我可以产生这个:

>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608
>>> id([1, 2])
4330529608

但是在IPython或IPython Notebook中工作,你得到了这个:

In [1]: id([1, 2])
Out[1]: 4359684552

In [2]: id([1, 2])
Out[2]: 4379935816

In [3]: id([1, 2])
Out[3]: 4373482696

In [4]: id([1, 2])
Out[4]: 4359674248

In [5]: id([1, 2])
Out[5]: 4373482696

这是因为IPython在后台做了一些工作,并创建了在创建新对象之前重用已释放id的对象。

答案 1 :(得分:1)

引自the docs(强调我的):

  的 id ( object )      

返回对象的“标识”。这是一个整数,保证是唯一且恒定的   这个对象在其生命周期中。 两个非重叠的对象   生命周期可能具有相同的id()

     

CPython实现细节:这是对象的地址   存储器

基本上,当您编写id([1, 2])时,您创建一个列表,检查其id,并将其丢弃,这使其有资格进行垃圾回收。在CPython中,由于通过引用计数进行垃圾收集,它会被删除,并且没有任何禁止在内存中完全相同的位置创建另一个对象,因此具有相同的id