Python 中函数的接口id()对我来说很清楚:\n“对象\xe2\x80\x99s 身份一旦创建就永远不会改变” [1],并且\n“这是一个保证唯一的整数并且该对象在其生命周期内保持不变。” [2]
但[1]中的这个说法让我很困惑:“你可能会认为它是内存中的对象\xe2\x80\x99s地址”。
\n\n问题是不清楚对象在内存中的地址是什么以及它如何变化。我认为这确实是一个实现细节。这个问题似乎表明,要使语言参考中的这一陈述成立,对象的虚拟地址在实现中决不能改变。
\n\n我的问题是:
\n\n这个地址是指虚拟内存地址还是物理内存地址?任何进程的物理地址都是由操作系统在运行时确定的,因此我不明白它如何是物理的。
实现如何保持虚拟对象地址相同,同时仍然避免内部碎片?相比之下,在 Java 中,JVM 例程在 GC 期间移动对象。
事实上,对象id的 是由实现定义的,只要它 a)在其生命周期内是唯一且恒定的(虽然与这个问题无关:这确实意味着id如果第一个对象的生命周期结束,两个对象可以具有相同的值) )。
CPython 实现确实具有不变性,即对象始终固定在其原始内存位置并且从不移动。当涉及到与 C 的互操作性时,这具有巨大的好处,因为只要对象保持活动状态(通常只是递增的引用计数器),您就可以自由地传递指针,这些指针将保持有效。
鉴于此,CPython 解释器仅使用对象的虚拟内存地址,如下所示id:
id是安全的,因为如果存储该id对象,删除原始对象,重新使用id(我以前见过这个对象吗?)并陷入混乱,他就违反了以下规则:id只有当它所代表的对象还活着时,the才有效。另请注意,重新分配不会更改对象的虚拟地址。例如,该list对象有一个指向元素向量的内部指针。id-object 的是其自身list的虚拟地址PyListObject。当列表增长并需要重新分配/移动到其他地方时,仅更改内部指针;留PyListObject在原来的地方,因此它id保持不变。
以下是current 中内置函数的完整定义id()HEAD:
static PyObject *
builtin_id(PyModuleDef *self, PyObject *v)
{
return PyLong_FromVoidPtr(v);
}
Run Code Online (Sandbox Code Playgroud)
没有烟,没有镜子。这只是指针。
| 归档时间: |
|
| 查看次数: |
364 次 |
| 最近记录: |