当前位置: 代码迷 >> python >> 变量名称如何在内部存储和映射?
  详细解决方案

变量名称如何在内部存储和映射?

热度:38   发布时间:2023-06-16 10:08:04.0

我阅读了 ,似乎在 CPython 中,变量只是与引用关联的名称。

语句 x=5 有几件事情发生:

  1. 一个值为 5 的 int 对象被创建(或者如果它已经存在则找到)
  2. 名称 x 被创建(或与最后一个标记为“x”的对象解除关联)
  3. 对新(或找到)int 对象的引用计数增加 1
  4. 名称 x 与创建(或找到)值为“5”的对象相关联。

但是,我仍然不清楚变量是如何在内部实现的。

即:

  1. 名称 x 被创建(或与最后一个标记为“x”的对象解除关联);

那名字不会也占用内存空间吗? sys.sizeof(x)等于sys.sizeof(5) ,我知道sys.sizeof(x)只能返回关联引用的大小,但是名称x的大小是多少?

  1. 名称 x 与创建(或找到)值为“5”的对象相关联

这是如何在内部实施的? 我认为在高层次上它可以用dict来完成,其中键是变量名( str ?),值是与之关联的引用。

我认为在高层次上它可以用 dict 来完成,其中键是变量名(str?),值是与之关联的引用。

这也是它内部的工作方式。 在 CPython 中,变量名和它们指向的对象通常存储在 Python 字典中; 与编写 Python 代码时可以使用的数据结构完全相同。

当你写x = 5 ,名称x被设置为全局名称字典中的键,对应的值为 5。 您可以使用globals()函数返回并检查此字典,该函数提供当前作用域命名空间的内容。

因此,名称x占用空间也是正确的。 它作为内存中某处的字符串存在,Python 为字典的键保留对它的引用。

如果您想更深入地查看 CPython 源代码以查看x在何处分配给值 5,您可以查看 ceval.c。 写入x = 5会触发LOAD_CONST操作码(将整数 5 放入堆栈)和STORE_GLOBAL操作码*(将名称x设置为字典中的键,值为 5)。

STORE_GLOBAL操作码的代码:

TARGET(STORE_GLOBAL) {
    PyObject *name = GETITEM(names, oparg);
    PyObject *v = POP();
    int err;
    err = PyDict_SetItem(f->f_globals, name, v);
    Py_DECREF(v);
    if (err != 0)
        goto error;
    DISPATCH();
}

您可以看到调用PyDict_SetItem以更新全局字典。


* 如果您检查x = 5生成的字节码(例如使用dis ),您可能会看到使用的操作码。 此操作码的功能相同(请参阅 的简要说明)。

  相关解决方案