__slots__ 类属性

使用 slots 类属性节省空间

知识点:

1) slots__限制实例随意增加属性,而__setattr__内建函数则不允许访问不存在的属性
2) 存在__slots__的类不存在__dict
,访问会引发AttributeError
3) dict__属性跟踪所有的实例属性,返回的是一个字典,占用内存较多,基于内存考虑的话可以用__slots__代替__dict

默认情况下,Python 在各个实例中名为 dict 的字典里存储实例属性。为了使用底层的散列表提升访问速度,字典会消耗大量内存。如果要处理数百万个属性不多的实例,通过 __slots__类属性,能节省大量内存,方法是让解释器在元组中存储实例属性,而不用字典。
继承自超类的 slots 属性没有效果。Python 只会使用各个类中定义的 slots 属性。定义 slots 的方式是,创建一个类属性,使用 slots 这个名字,并把它的值设为一个字符串构成的可迭代对象,其中各个元素表示各个实例属性。我喜欢使用元组,因为这样定义的 slots 中所含的信息不会变化,如下 所示。

# 只在 Vector2d 类中添加了__slots__ 属性
class Vector2d:
	__slots__ = ('__x', '__y')
	typecode = 'd'

在类中定义 slots 属性的目的是告诉解释器:“这个类中的所有实例属性都在这儿了!”这样,Python 会在各个实例中使用类似元组的结构存储实例变量,从而避免使用消耗内存的 dict 属性。如果有数百万个实例同时活动,这样做能节省大量内存。

效率比较
我们运行两个构建列表的脚本,这两个脚本都使用列表推导创建 10 000 000 个 Vector2d 实例。mem_test.py 脚本的命令行参数是一个模块的名字,模块中定义了不同版本的 Vector2d 类。第一次运行使用的是 vector2d_v3.Vector2d 类(在示例 9-7 中定义),第二次运行使用的是定义了 slots 的vector2d_v3_slots.Vector2d 类。

$ time python3 mem_test.py vector2d_v3.py
Selected Vector2d type: vector2d_v3.Vector2d
Creating 10,000,000 Vector2d instances
Initial RAM usage: 5,623,808
Final RAM usage: 1,558,482,944
real 0m16.721s
user 0m15.568s
sys 0m1.149s

$ time python3 mem_test.py vector2d_v3_slots.py
Selected Vector2d type: vector2d_v3_slots.Vector2d
Creating 10,000,000 Vector2d instances
Initial RAM usage: 5,718,016
Final RAM usage: 655,466,496
real 0m13.605s
user 0m13.163s
sys 0m0.434s

如上 所示,在 10 000 000 个 Vector2d 实例中使用 dict 属性时,RAM 用量高达 1.5GB;而在 Vector2d 类中定义 slots 属性之后,RAM 用量降到了 655MB。此外,定义了 slots 属性的版本运行速度也更快

slots 的问题

  • 每个子类都要定义 slots 属性,因为解释器会忽略继承的 slots 属性。
  • 实例只能拥有 slots 中列出的属性,除非把 ‘dict’ 加 入 slots 中(这样做就失去了节省内存的功效)
  • 如果不把 ‘weakref’ 加入 slots,实例就不能作为弱引用的目标。

如果你的程序不用处理数百万个实例,或许不值得费劲去创建不寻常的
类,那就禁止它创建动态属性或者不支持弱引用。与其他优化措施一
样,仅当权衡当下的需求并仔细搜集资料后证明确实有必要时,才应该
使用 slots 属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值