当前位置: 首页 > news >正文

python中类变量 __slots__ 解析

        在 Python 中,__slots__ 是一个特殊的类属性,用于显式声明类实例允许的属性集。它通过替代默认的 __dict__ 字典存储机制,提供了内存优化和访问速度提升。

一. 核心作用

  • 内存优化:普通类实例的属性存储在动态字典 __dict__ 中,占用较多内存。使用 __slots__ 后,实例通过固定大小的数组存储属性,显著减少内存开销(约 40-50%)。

  • 访问速度提升:直接通过数组偏移量访问属性,比字典查找更快。

  • 防止动态属性创建:限制实例只能添加 __slots__ 中声明的属性,避免意外属性赋值。

二. 基本用法

        在 Python 中,使用 __slots__ 声明的属性不会在类声明后自动创建__slots__ 的作用是限制实例可拥有的属性,并为这些属性预留存储空间,但属性本身需要显式初始化(通常在 __init__ 方法中)。

class Person:__slots__ = ['name', 'age']  # 显式声明允许的属性def __init__(self, name, age):self.name = nameself.age = age# 正常使用
p = Person("Alice", 30)
print(p.name, p.age)  # Alice 30# 尝试添加未声明的属性 → 报错!
p.address = "Paris"  # AttributeError: 'Person' object has no attribute 'address'

关键点:

声明 ≠ 初始化

        __slots__ 仅声明允许的属性名称,不会自动创建或初始化这些属性。直接访问未初始化的属性会引发 AttributeError。

class MyClass:__slots__ = ['name', 'age']obj = MyClass()
print(obj.name)  # AttributeError: 'name' 未初始化

 必须显式赋值

        属性需在 __init__ 或其他方法中显式赋值后才会存在:

class MyClass:__slots__ = ['name', 'age']def __init__(self, name, age):self.name = name  # 正确初始化self.age = age    # 正确初始化obj = MyClass("Alice", 30)
print(obj.name)  # 输出: Alice

节省内存的原理

__slots__ 通过以下方式优化内存:

  • 取消实例的 __dict__(禁止动态添加属性)。

  • 为 __slots__ 中的属性预先分配固定存储空间(类似 C 结构体)。

使用__slots__浪费内存的情况

  1. 有浪费但可控

    • 未使用槽位会占用空间(每个约 8 字节)

    • 但远小于 __dict__ 的基准开销(通常 240+ 字节)

  2. 何时真正浪费

    • 声明大量永不使用的属性(如声明 100 个只用到 5 个)

    • 实例数量极少时(优化效果不明显)

三. 关键特性

  • 无 __dict__:默认情况下,使用 __slots__ 的类实例不再拥有 __dict__(除非显式包含)。

  • 禁止动态属性:无法添加未在 __slots__ 中声明的属性。

  • 类属性不受限__slots__ 仅限制实例属性,类属性可正常使用。

  • 继承行为

    • 子类未定义 __slots__:继承父类的 __slots__,同时拥有 __dict__(可动态添加属性)。

    • 子类定义 __slots__:继承父类的 __slots__,子类 __slots__ 为其父类与自己声明的并集。

四. 高级用法

(1) 保留 __dict__
class Person:__slots__ = ['name', 'age', '__dict__']  # 显式包含 __dict__def __init__(self, name, age):self.name = nameself.age = agep = Person("Bob", 25)
p.gender = "Male"  # 允许动态属性(存储在 __dict__ 中)
(2) 支持弱引用
class Person:__slots__ = ['name', '__weakref__']  # 显式包含 __weakref__p = Person()
import weakref
ref = weakref.ref(p)  # 弱引用生效

五. 继承示例

# 父类
class Base:__slots__ = ['base_attr']# 子类未定义 __slots__
class ChildA(Base):passa = ChildA()
a.base_attr = 1   # 正常(继承自 Base)
a.new_attr = 2    # 正常(ChildA 有 __dict__)# 子类定义 __slots__
class ChildB(Base):__slots__ = ['child_attr']b = ChildB()
b.base_attr = 1   # 正常
b.child_attr = 2  # 正常
b.new_attr = 3    # AttributeError(无 __dict__)

六. 性能对比

内存占用
import sysclass WithoutSlots:passclass WithSlots:__slots__ = ['x', 'y']# 创建大量实例
instances = [WithoutSlots() for _ in range(100000)]
print(sys.getsizeof(instances[0].__dict__))  # ≈ 120-280 字节/实例instances = [WithSlots() for _ in range(100000)]
print(sys.getsizeof(instances[0]))          # ≈ 32-48 字节/实例

 访问速度

import timeitsetup = """
class WithoutSlots: pass
class WithSlots: __slots__ = ['x']obj1 = WithoutSlots()
obj2 = WithSlots()
"""print(timeit.timeit("obj1.x = 1", setup, number=10**7))  # ≈ 0.8s
print(timeit.timeit("obj2.x = 1", setup, number=10**7))  # ≈ 0.6s(快 20-30%)

七. 使用场景

  • 大量实例:处理成千上万对象(如游戏角色、科学计算数据)。

  • 内存敏感环境:嵌入式系统、内存受限场景。

  • 安全限制:防止意外添加属性(类似 "final" 类)。

  • 性能关键代码:高频属性访问场景。

八. 注意事项

  1. 不兼容旧代码:依赖 __dict__ 或 __weakref__ 的库需显式声明。

  2. 继承冲突:多继承中父类 __slots__ 冲突会导致未定义行为。

  3. 工具兼容性:部分序列化/调试工具依赖 __dict__

  4. 只读属性:无法完全替代 @property 实现只读属性。

总结

__slots__ 是 Python 中优化内存和性能的重要工具,适用于大规模实例场景。在明确属性集、无需动态扩展时,它能显著提升效率。但需权衡灵活性损失,谨慎用于继承结构复杂的项目。

http://www.dtcms.com/a/303432.html

相关文章:

  • Matplotlib(三)- 图表辅助元素
  • Vue3判断对象是否为空方法
  • 飞鹤困局:增长神话的裂痕
  • 嵌软面试——通信协议
  • 7.项目起步(1)
  • 1.vue体验
  • 快速构建基于React.js的用户注册与登录的Web应用程序
  • vue element 封装表单
  • 代码随想录算法训练营第三十三天
  • 7.28PBR技术
  • Linux系统编程——数据库
  • 介绍一下static关键字
  • Sum-rate计算
  • 【代码解读】通义万相最新视频生成模型 Wan 2.2 实现解析
  • 同态滤波算法详解:基于频域变换的光照不均匀校正
  • 栈算法之【用栈实现队列】
  • 凸优化:凸函数的一些常用性质
  • OpenLayers 综合案例-量测工具
  • 【Zustand】从复杂到简洁:Zustand 状态管理简化实战指南
  • 图解系统的学习笔记--硬件结构
  • 告别繁琐 Mapper!Stream-Query 正式入驻 GitCode 平台
  • GPFS文件系统更换磁盘
  • 企业级JWT验证最佳方案:StringUtils.hasText()
  • AD中放置过孔阵列
  • Python 异常 (Exception) 深度解析
  • 如何获取我当前的IP地址
  • 掌握 ArkTS 复杂数据绑定:从双向输入到多组件状态同步
  • AWS MemoryDB 可观测最佳实践
  • Python Pandas.merge_ordered函数解析与实战教程
  • 全球首个1米高精度特大城市开放空间数据集(Tif)