初学代码时总有一个问题困扰我:a = 10 # a指向地址0x1234(存储10) 变量a的值10存储在0x1234,那么变量a需要存储吗?a又存储在什么地址呢
目录
1. 命名空间的本质
2. 命名空间的内存占用
3. 变量名 vs 变量值的存储对比
4. 静态语言(如C)的对比
5. 为什么需要命名空间?
6. 总结
7.小测试
1. 命名空间的本质
动态语言(如Python): 变量名与值的绑定关系通过 命名空间字典(如 globals())维护,但这个字典本身是一个 运行时动态创建的对象,存储在内存中。
变量名 "a":作为字典的 键(Key)(字符串对象)存储。变量值 10:作为字典的 值(Value)(指向实际对象的引用)。
# 伪代码展示Python内部实现(简化版)
global_namespace = {
"a": 0x1234, # 键是字符串"a",值是对象10的地址
"b": 0x5678 # 其他变量...
}
2. 命名空间的内存占用
存储位置: 命名空间字典本身是一个 堆内存中的对象,有独立的内存地址(可通过 id(globals()) 查看)。 print(hex(id(globals()))) # 输出如0x55a1b2d3e0(命名空间字典的地址) 内存消耗:
每个键(变量名)作为字符串对象存储,占用内存。每个值(变量引用)是指针(通常8字节,64位系统)。字典的哈希表结构还有额外开销(如哈希桶、冲突处理)。
3. 变量名 vs 变量值的存储对比
存储内容存储位置示例(Python)变量名 "a"命名空间字典的键(堆内存)globals()["a"] 中的 "a"变量值 10独立对象(堆内存)id(a) 返回的地址(如 0x1234)命名空间字典堆内存中的对象id(globals()) 返回的地址(如 0x55a1b2d3e0)
4. 静态语言(如C)的对比
无运行时命名空间: 变量名在编译后直接替换为固定内存地址,不占用运行时内存。 int a = 10; // 编译后,所有对a的访问变为对地址0x1000的操作 无字典开销: 变量名仅在源码和符号表中存在,编译后的二进制文件中无痕迹。
5. 为什么需要命名空间?
动态语言的灵活性: Python 允许运行时动态添加/删除变量(如 globals()["x"] = 100),必须维护变量名与值的映射关系。作用域管理: 每个函数有独立的 locals() 字典,实现变量隔离。
6. 总结
变量名存储:作为字符串键存在于命名空间字典中(堆内存)。命名空间存储:字典对象本身占用内存(地址可通过 id(globals()) 获取)。核心区别:
静态语言:变量名是编译期概念,无运行时存储。动态语言:变量名是运行时对象,需内存存储以支持动态特性。
7.小测试
多个变量的值相同的情况下,内存空间里是如何存储的?(答案在下期)举例:a=b=c=10
这种设计是 Python 等动态语言灵活性的代价——牺牲部分内存和速度换取开发便捷性。
元宝老师提供标准化答案,解释权归迪普斯克老师,侵删~