如何在内部存储和映射变量名称?
How are variables names stored and mapped internally?
我读过 并且在 CPython 中,变量似乎只是与引用关联的名称。
There are several things going on with the statement x=5:
- an int object with the value of 5 is created (or found if it already
exists)
- the name x is created (or disassociated with the last object
'x' labeled)
- the reference count to the new (or found) int object is
increased by 1
- the name x is associated with the object with the
value '5' created (or found).
但是,我仍然不清楚变量在内部是如何实现的。
即:
- the name x is created (or disassociated with the last object 'x' labeled);
那名字不也占内存吗space? sys.sizeof(x)
等于 sys.sizeof(5)
,我知道 sys.sizeof(x)
只能 return 关联引用的大小,但是名称 x
的大小是多少?
- the name x is associated with the object with the value '5' created (or found)
这在内部是如何实现的?我认为在高层次上它可以用 dict
来完成,其中键是变量名(str
?),值是它关联的引用。
I think at a high level it can be done with a dict, where the key is the variable name (str?) and the value is the reference that it's associated with.
这也是它在内部的工作方式。在 CPython 中,变量名和它们指向的对象通常存储在 Python 字典中;您在编写 Python 代码时可以使用的相同数据结构。
当你写x = 5
时,名称x
被设置为全局名称字典中的一个关键字,5作为对应的值。您可以 return 并使用 globals()
函数检查此字典,该函数给出当前作用域名称 space.
的内容
因此您也正确地认为名称 x
占用了 space。它作为字符串存在于内存中的某处,Python 保留对它的引用作为字典的键。
如果您想更深入地查看 CPython 源代码以查看 x
在哪里被分配给值 5,您可以查看 ceval.c。写入 x = 5
会触发 LOAD_CONST
操作码(将整数 5 放入堆栈)以及 STORE_GLOBAL
操作码*(将名称 x
设置为字典中的键以 5 作为值)。
Here 是 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
),您可能会看到 STORE_NAME
opcode used. This opcode functions in the same way (see here 的简短描述。
我读过 并且在 CPython 中,变量似乎只是与引用关联的名称。
There are several things going on with the statement x=5:
- an int object with the value of 5 is created (or found if it already exists)
- the name x is created (or disassociated with the last object 'x' labeled)
- the reference count to the new (or found) int object is increased by 1
- the name x is associated with the object with the value '5' created (or found).
但是,我仍然不清楚变量在内部是如何实现的。
即:
- the name x is created (or disassociated with the last object 'x' labeled);
那名字不也占内存吗space? sys.sizeof(x)
等于 sys.sizeof(5)
,我知道 sys.sizeof(x)
只能 return 关联引用的大小,但是名称 x
的大小是多少?
- the name x is associated with the object with the value '5' created (or found)
这在内部是如何实现的?我认为在高层次上它可以用 dict
来完成,其中键是变量名(str
?),值是它关联的引用。
I think at a high level it can be done with a dict, where the key is the variable name (str?) and the value is the reference that it's associated with.
这也是它在内部的工作方式。在 CPython 中,变量名和它们指向的对象通常存储在 Python 字典中;您在编写 Python 代码时可以使用的相同数据结构。
当你写x = 5
时,名称x
被设置为全局名称字典中的一个关键字,5作为对应的值。您可以 return 并使用 globals()
函数检查此字典,该函数给出当前作用域名称 space.
因此您也正确地认为名称 x
占用了 space。它作为字符串存在于内存中的某处,Python 保留对它的引用作为字典的键。
如果您想更深入地查看 CPython 源代码以查看 x
在哪里被分配给值 5,您可以查看 ceval.c。写入 x = 5
会触发 LOAD_CONST
操作码(将整数 5 放入堆栈)以及 STORE_GLOBAL
操作码*(将名称 x
设置为字典中的键以 5 作为值)。
Here 是 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
),您可能会看到 STORE_NAME
opcode used. This opcode functions in the same way (see here 的简短描述。