Python空类内存占用构成及sys.getsizeof与dir统计差异疑问
Python中空类、实例与空函数的内存占用分析
问题背景
我用Python 3.12.3编写了一段代码,对比空类、空类实例和空函数的内存占用:
import sys class EmptyClass: pass def empty_func(): pass print(f"Class size: {sys.getsizeof(EmptyClass)}") print(f"Instance size: {sys.getsizeof(EmptyClass())}") print(f"Function size: {sys.getsizeof(empty_func)}") # 统计对象属性的内存总和 def get_mem_size(obj): mem = 0 for name in dir(obj): attr = getattr(obj, name) mem += sys.getsizeof(attr) return mem print(f"Class dir size: {get_mem_size(EmptyClass)}") print(f"Function dir size: {get_mem_size(empty_func)}")
运行输出:
Class size: 1704 Instance size: 48 Function size: 160 Class dir size: 2185 Function dir size: 12287
我原本认为空类的内存占用应该等于其类变量和方法的总大小(通过dir(obj)统计),但实际sys.getsizeof(EmptyClass)结果为1704,而dir统计的内存足迹为2185,二者存在差异。另外我想了解Python中空类的内存由哪些组件构成,以及如何通过这些组件明确计算其内存占用。
核心解释与答案
1. 两种统计方式的差异本质
sys.getsizeof(obj)仅返回对象自身直接占用的内存,不包含它引用的其他对象的内存。而dir(obj)会列出对象的所有属性(包括从父类继承的),get_mem_size统计的是这些属性对象各自的内存总和——这些属性本身是独立的对象(比如类的__dict__、__module__字符串、继承的方法等),它们的内存不算在类对象自身的sys.getsizeof结果里。
举个直观例子:EmptyClass的__dict__是一个字典对象,sys.getsizeof(EmptyClass)只计算这个字典对象的指针大小,而get_mem_size会把整个字典的内存(包括字典内存储的内容)加进去,这直接导致了数值差异。
2. 空类的内存构成(Python 3.12)
空类EmptyClass作为type的实例,其内存主要由以下部分构成:
- 基础对象头:所有Python对象共有的元数据,包括引用计数、类型指针等,64位系统上通常占16字节。
- 类核心结构:
- 指向父类(如
object)的指针 - 类名称字符串的指针
- 类所属模块信息的指针
- 类的
__dict__指针(用于存储类变量和自定义方法) - 类的方法缓存(加速属性查找)
- 类型相关的内部标记、标志位
- 指向父类(如
- 内部存储结构:用于支持描述符、继承链的额外空间,以及解释器为类对象预分配的缓存区。
3. 准确计算类的总内存占用
如果要统计类对象及其所有引用对象的总内存,sys.getsizeof无法满足需求,需要递归遍历对象的所有引用并累加:
import sys from gc import get_referents def get_total_size(obj): seen = set() def inner(obj): if id(obj) in seen: return 0 seen.add(id(obj)) size = sys.getsizeof(obj) # 递归统计所有引用对象的内存 for referent in get_referents(obj): size += inner(referent) return size return inner(obj) class EmptyClass: pass print(f"EmptyClass 总内存占用: {get_total_size(EmptyClass)}")
这个函数会递归计算对象自身和所有直接/间接引用对象的内存总和,能更准确反映类的实际内存足迹。
补充说明
- 空类实例的48字节:64位Python中,空实例的内存包含对象头+实例
__dict__指针(无__slots__时),加上内存对齐字节,总大小为48字节。 - 空函数的160字节:函数对象包含代码对象指针、名称指针、闭包信息、默认参数存储等基础结构,这些结构的总大小在Python 3.12中为160字节。
内容的提问来源于stack exchange,提问作者maxbalrog
相关产品推荐
相关产品推荐

