当前位置: 首页 > 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.lryc.cn/news/602298.html

相关文章:

  • 5190 - 提高:DFS序和欧拉序:树上操作(区域修改1)
  • 排序算法 (Sorting Algorithms)-JS示例
  • AI原生应用:从人机关系重构到数字空间革命
  • RF随机森林分类预测+特征贡献SHAP分析,通过特征贡献分析增强模型透明度,Matlab代码实现,引入SHAP方法打破黑箱限制,提供全局及局部双重解释视角
  • 力扣7:整数反转
  • OCR 赋能合同抽取:不良资产管理公司的效率加速器
  • Kafka 顺序消费实现与优化策略
  • 数据结构之顺序表链表栈
  • 【Git】Linux-ubuntu 22.04 初步认识 -> 安装 -> 基础操作
  • 图片PDF识别工具:扫描PDF文件批量OCR区域图识别改名,识别大量PDF区域内容一次性改名
  • 基于LSTM和GRU的上海空气质量预测研究
  • 图片上传 el+node后端+数据库
  • 如何用VUE实现用户发呆检测?
  • Android通知(Notification)全面解析:从基础到高级应用
  • 【前端】解决Vue3+Pinia中Tab切换与滚动加载数据状态异常问题
  • 05 OpenCV--图像预处理之图像轮廓、直方图均衡化、模板匹配、霍夫变化、图像亮度变化、形态学变化
  • 数据结构:下三角矩阵(Lower Triangular Matrix)
  • MySQL SQL性能优化与慢查询分析实战指南:新手DBA成长之路
  • Eigen 中矩阵的拼接(Concatenation)与 分块(Block Access)操作使用详解和示例演示
  • 简明量子态密度矩阵理论知识点总结
  • 搜索二维矩阵Ⅱ C++
  • 【LeetCode】算法详解#10 ---搜索二维矩阵II
  • 秩为1的矩阵的特征和性质
  • 青少年编程高阶课程介绍
  • 青少年编程中阶课
  • 『 C++ 入门到放弃 』- 哈希表
  • 攻防世界-引导-Web_php_unserialize
  • 《LeetCode 热题 100》整整 100 题量大管饱题解套餐 中
  • cacti的RCE
  • 关于“PromptPilot” 之3 -Prompt构造器核心专项能力:任务调度