__slots__ ()是 Python 中一个非常特殊且有用的类属性声明它的核心作用是禁止实例拥有__dict__从而彻底阻止动态添加实例属性并最小化内存占用。下面分层解析它的作用、原理和使用场景。一、__slots__是做什么的默认情况下Python 类的每个实例都有一个__dict__字典用来存储实例的属性。classUser:passuUser()u.nameJimmy# 动态添加属性print(u.__dict__)# {name: Jimmy}__slots__的作用是告诉 Python这个类的实例只允许拥有哪些属性不要用__dict__来存储。二、__slots__ ()的特殊含义classImmutablePoint:__slots__()这表示✅这个类的实例不允许有任何实例属性✅实例不会有__dict__✅不能动态添加属性pImmutablePoint()p.x1# ❌ AttributeError错误信息类似AttributeError: ImmutablePoint object has no attribute x三、对比不同写法写法是否有__dict__能否动态加属性说明普通类✅ 有✅ 能默认行为__slots__ (x, y)❌ 没有✅ 仅限 x, y限制属性__slots__ ()❌ 没有❌ 完全不能最严格四、为什么要这样用1️⃣ 防止误用强制“纯行为类”适合用于只包含方法、不包含状态的工具类classMathUtils:__slots__()staticmethoddefadd(a,b):returnab✅ 防止有人错误地给工具类加实例属性✅ 提高语义清晰度2️⃣ 基类设计中“锁死”实例状态常用于抽象基类 / MixinclassNonDataClassBase:__slots__()子类可以继续定义自己的__slots__但不会意外引入__dict__保证整条继承链的内存紧凑性3️⃣ 极致内存优化大数据场景假设你要创建数百万个对象classNormal:passclassOptimized:__slots__()类内存占用Normal~72 bytes __dict__Optimized~56 bytes无__dict__✅ 每个实例节省几十字节✅ 百万级对象 MB 级差异4️⃣ 与dataclass(frozenTrue)配合fromdataclassesimportdataclassdataclass(frozenTrue)classPoint:__slots__()x:inty:int效果不可变无__dict__最小内存线程安全逻辑层面这是很多**高性能库如 Pydantic、attrs**常用的技巧。五、在 Pydantic / FastAPI 中的真实案例在看 Pydantic 源码时经常会看到classBaseModel:__slots__()原因正是Pydantic 自己管理字段__fields__不需要实例__dict__防止用户随意添加属性破坏模型约束减少内存占用六、注意事项 坑点⚠️ 1. 子类必须也定义__slots__否则子类会重新获得__dict__classA:__slots__()classB(A):passbB()b.x1# ✅ 居然可以✅ 正确做法classB(A):__slots__(x,)⚠️ 2. 无法使用某些依赖__dict__的特性不能直接用vars(obj)某些序列化库可能不兼容调试时不如普通对象直观⚠️ 3. 多重继承要小心多个定义了__slots__的类混用容易出问题。七、一句话总结__slots__ ()的作用是禁止实例拥有动态属性移除__dict__强制类成为“无状态”或“严格受控状态”的结构常用于工具类、基类和高性能场景。八、什么时候该用✅ 适合纯方法工具类基类 / Mixin不可变对象大规模对象创建❌ 不适合需要动态属性的业务模型快速原型开发依赖__dict__的第三方库
__slots__ = ()
发布时间:2026/7/9 11:57:28
__slots__ ()是 Python 中一个非常特殊且有用的类属性声明它的核心作用是禁止实例拥有__dict__从而彻底阻止动态添加实例属性并最小化内存占用。下面分层解析它的作用、原理和使用场景。一、__slots__是做什么的默认情况下Python 类的每个实例都有一个__dict__字典用来存储实例的属性。classUser:passuUser()u.nameJimmy# 动态添加属性print(u.__dict__)# {name: Jimmy}__slots__的作用是告诉 Python这个类的实例只允许拥有哪些属性不要用__dict__来存储。二、__slots__ ()的特殊含义classImmutablePoint:__slots__()这表示✅这个类的实例不允许有任何实例属性✅实例不会有__dict__✅不能动态添加属性pImmutablePoint()p.x1# ❌ AttributeError错误信息类似AttributeError: ImmutablePoint object has no attribute x三、对比不同写法写法是否有__dict__能否动态加属性说明普通类✅ 有✅ 能默认行为__slots__ (x, y)❌ 没有✅ 仅限 x, y限制属性__slots__ ()❌ 没有❌ 完全不能最严格四、为什么要这样用1️⃣ 防止误用强制“纯行为类”适合用于只包含方法、不包含状态的工具类classMathUtils:__slots__()staticmethoddefadd(a,b):returnab✅ 防止有人错误地给工具类加实例属性✅ 提高语义清晰度2️⃣ 基类设计中“锁死”实例状态常用于抽象基类 / MixinclassNonDataClassBase:__slots__()子类可以继续定义自己的__slots__但不会意外引入__dict__保证整条继承链的内存紧凑性3️⃣ 极致内存优化大数据场景假设你要创建数百万个对象classNormal:passclassOptimized:__slots__()类内存占用Normal~72 bytes __dict__Optimized~56 bytes无__dict__✅ 每个实例节省几十字节✅ 百万级对象 MB 级差异4️⃣ 与dataclass(frozenTrue)配合fromdataclassesimportdataclassdataclass(frozenTrue)classPoint:__slots__()x:inty:int效果不可变无__dict__最小内存线程安全逻辑层面这是很多**高性能库如 Pydantic、attrs**常用的技巧。五、在 Pydantic / FastAPI 中的真实案例在看 Pydantic 源码时经常会看到classBaseModel:__slots__()原因正是Pydantic 自己管理字段__fields__不需要实例__dict__防止用户随意添加属性破坏模型约束减少内存占用六、注意事项 坑点⚠️ 1. 子类必须也定义__slots__否则子类会重新获得__dict__classA:__slots__()classB(A):passbB()b.x1# ✅ 居然可以✅ 正确做法classB(A):__slots__(x,)⚠️ 2. 无法使用某些依赖__dict__的特性不能直接用vars(obj)某些序列化库可能不兼容调试时不如普通对象直观⚠️ 3. 多重继承要小心多个定义了__slots__的类混用容易出问题。七、一句话总结__slots__ ()的作用是禁止实例拥有动态属性移除__dict__强制类成为“无状态”或“严格受控状态”的结构常用于工具类、基类和高性能场景。八、什么时候该用✅ 适合纯方法工具类基类 / Mixin不可变对象大规模对象创建❌ 不适合需要动态属性的业务模型快速原型开发依赖__dict__的第三方库