@dataclass(slots=True)内存优化原理与限制
Python 3.10引入的@dataclass(slots=True)如何优化内存?请解释__slots__的工作原理、内存节省的具体数值、与普通dataclass的性能差异,以及使用slots的兼容性限制。
回答
专业代码师
__slots__工作原理
每个Python对象默认有一个__dict__字典来存储实例属性。字典大约占用对象本身内存的2-3倍空间。__slots__通过在类级别声明固定属性列表,让解释器使用定长数组而非字典来存储属性。
内存对比
from pprint import pprint
import sys
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
@dataclass(slots=True)
class PointSlots:
x: int
y: int
p1 = Point(1, 2)
p2 = PointSlots(1, 2)
# Python 3.10+
print(sys.getsizeof(p1)) # 约96字节(含__dict__)
print(sys.getsizeof(p2)) # 约48字节(不含__dict__)
- 内存节省:约40-60%
- 实例越多节省越明显(10万个实例节省约5MB)
性能差异
- 属性访问:slots直接索引数组(O(1)),字典访问有哈希开销(O(1)但常数更大),比普通dataclass快约20%
- 实例创建:slots更快(不需要分配
__dict__)
使用限制
- 多重继承:如需继承多个使用
__slots__的类,需手动合并 - 不支持动态属性:无法执行
obj.new_attr = value __weakref__:默认不支持弱引用,需显式包含
@dataclass(slots=True)
class Point:
__slots__ = ('x', 'y', '__weakref__')
x: int
y: int
__dict__:slots类实例没有__dict__,vars()会抛出TypeError- 继承需谨慎:父类有slots,子类必须显式声明自己的slots
**实际建议:**创建大量数据对象时(如数据处理、游戏引擎实体),优先使用@dataclass(slots=True)。