Python内存管理见解 - id()

时间:2011-07-18 13:17:40

标签: python

id()。开始查看不同对象中相同属性的地址。但是现在我觉得这没关系。下到代码:

class T(object):
    pass

class N(object):
    pass

首次测试(在交互式控制台中):

n = N()
t = T()
id(n)
# prints 4298619728
id(t)
# prints 4298619792
实际上,这并不奇怪。 n.__class__t.__class__不同,因此很明显它们不可能是同一个对象。目前这些对象之间的__class__ 是否有差异?假设,为:

>>> n1 = N()
>>> n2 = N()
>>> id(n1) == id(n2)
False

或者Python只是创建单独的对象,即使它们在内容方面完全相同,而不是首先将名称n1n2分配给同一对象(在内存中)并在n1n2被修改时重新分配?为什么这样?我明白这可能是一个常规,优化,情绪,低级别问题的问题(不要饶恕我),但我仍然很好奇。

现在,和以前一样,T()& N() - 在shell中一个接一个地执行:

>>> id(N())
4298619728
>>> id(N())
4298619792
>>> id(N())
4298619728
>>> id(N())
4298619792

为什么玩杂耍?

但是这里出现了奇怪的部分。同样,相同的类,shell:

>>> id(N()), id(T())
(4298619728, 4298619728)
>>> id(N()), id(T())
(4298619728, 4298619728)
>>> id(N()), id(T())
(4298619728, 4298619728)

不仅杂耍停止,而且N()和T()似乎是同一个对象。由于它们不可能,我理解为N()id()调用后被撤销,在整个陈述结束之前

我意识到这可能是一个艰难的回答。但是我希望有人可以告诉我我在这里观察到的是什么,我的理解是否正确,分享一些关于解释器内部工作和记忆管理的黑暗魔法,或者可能指出一些关于这个主题的好资源?

感谢您抽出宝贵时间。

5 个答案:

答案 0 :(得分:6)

答案 1 :(得分:5)

文档says it all

  

id(object)

     

返回对象的“标识”。这是一个整数(或长整数)   整数)保证对于该对象是唯一的和常量的   在其一生中。两个具有非重叠寿命的对象可以   具有相同的id()值。

每当调用构造函数时,都会创建一个新对象。该对象的id与当前存活的任何其他对象的id不同

>>> n1 = N()
>>> n2 = N()
>>> id(n1) == id(n2)
False

两个对象的“内容”无关紧要。它们是两个不同的实体;他们会得到不同的ID似乎是完全合乎逻辑的。

在CPython中,id只是内存地址。它们确实被回收:如果一个对象被垃圾收集,将来某个时候创建​​的另一个对象可能获得相同的id。这是您在重复的id(N()), id(T())测试中看到的行为:由于您没有保留对新创建的对象的引用,因此解释器可以自由地收集它们并重用它们的ID。

ids的回收显然是一个实施/平台人工制品,不应该依赖。

答案 2 :(得分:1)

我可能错了,但我认为您正在看垃圾收集器。对N()或T()的调用会创建一个未存储在任何位置的对象,然后由GC拾取。之后,可以重复使用内存地址。

答案 3 :(得分:0)

如果您真的想要答案,请查看来源。

一般而言,除非语言保证值标识和对象标识相同,或保证实际发生(如某些情况下Java用字符串做),那么如果价值和对象标识不要感到惊讶不同。

答案 4 :(得分:0)

我认为可能会发生杂乱,因为python命令行解释器将先前执行的结果存储为_。在命令行上,我有杂耍,但在python文件中似乎没有发生。例如,代码:

print id(X())
print id(X())
print id(X())
print id(X())
print id(X())

制作

>>> print id(X())
3078933196
>>> print id(X())
3078933004
>>> print id(X())
3078932716
>>> print id(X())
3078933196
....

但是具有相同文本的python文件会生成输出

3079140908
3079140908
3079140908
3079140908
3079140908