首页 > 编程语言 >Python__slots__魔法

Python__slots__魔法

时间:2023-03-09 21:55:43浏览次数:45  
标签:__ slotted Python init dict bar slots

1、__slots__魔法

在Python中,每个类都有实例属性。默认情况下Python⽤⼀个字典(__dict__属性)来保存⼀个对象的实例 属性。这⾮常有⽤,因为它允许我们在运⾏时去设置任意的新属性。

然而,对于有着已知属性的⼩类来说,它可能是个瓶颈。这个字典浪费了很多内存。
Python不能在对象创建时直接分配多个固定量的内存来保存所有的属性。因此如果你创建许多对象(我指的是成千上万个),它会消耗掉很多内存。

不过还是有一个方法来规避这个问题。这个方法需要使用__slots__来告诉Python不要使用字典,而且只给一个固定集合的属性分配空间。

1.1 __slots__的两大好处

1、节省memory。在上面的例子里,如果我们看看barslotted_bar就看到,slotted_bar并没有__dict__bar却含有__dict____slots__正是通过避免定义动态的数据结构__dict__来实现对memory的节省(见下面code)

dir(bar) # see __dict__
# >> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a']

dir(bar_slotted) # no __dict__, instead see __slots__
# >> ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'a']

## __slots__ save memory: size of bar_slotted is significantly smaller than bar
from pympler import asizeof 
asizeof.asizeof(bar)
# >> 256 bytes
asizeof.asizeof(bar_slotted)
# >> 80 bytes
  1. access attributes更快。事实上,在CPython的实现里,__slots__是一个静态数据结构(static),里面存的是value references,比__dict__更快(见下面code)。
## (In Ipython) access attribute in bar_slotted is much faster than bar 
%timeit bar.a = "aaa"
# >> 76.8 ns ± 8.34 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit bar_slotted.a = "aaa" 
# >> 55.7 ns ± 1.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

此处要注意一点,正因为__slots__是static的,定义了__slots__之后,你将不能创造新的attribute(见下面例子):

## cannot create an attribute named b for slotted_bar, but OK for bar
bar.b = "bbb" # OK

bar_slotted.b = "bbb" # Error below
# ---------------------------------------------------------------------------
# AttributeError                            Traceback (most recent call last)
# <ipython-input-12-9a36b223fad1> in <module>
# ----> 1 bar_slotted.b = "bbb"

#AttributeError: 'BarSlotted' object has no attribute 'b'

如果你想获得__slots__的好处并且可以创造新的attribute,你可以将__dict__作为__slots__中的一个element(见下面code):

class BarSlottedWithDict(object):
  __slots__ = "__dict__", "a"
  def __init__(self, a):
    self.a = a

bar_slotted_w_dict = BarSlottedWithDict(1)
bar_slotted_w_dict.b = 2

## bar_slotted_w_dict has both __dict__ and __slots__
dir(bar_slotted_w_dict)                                         
# >> ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'a', 'b']

1.2 什么情况下该使用__slots__?

当你事先知道class的attributes的时候,建议使用slots来节省memory以及获得更快的attribute access。

注意不应当把防止创造__slots__之外的新属性作为使用__slots__的原因,可以使用decorators以及getters,setters来实现attributes control。

内存占用情况

普通方法 > _slots_ = "_dict_", "a" > _slots_ = "a"

标签:__,slotted,Python,init,dict,bar,slots
From: https://www.cnblogs.com/jzYe/p/17201614.html

相关文章

  • 2023.3.9
    学习时间:2小时代码行数:200行今天学习了python的相关知识,Python进制函数,常见的有bin()#二进制,二进制数字格式为0b**,oct()#八进制,八进制数字格式为0o**,hex()#十六进制......
  • 2023 最新 Three.js 快速入门教程 All In One
    2023最新Three.js快速入门教程AllInOneThree.js核心概念Shader着色器Render渲染器材质贴图纹理骨骼动画网格几何体模型灯光摄像机相机场景舞台......
  • redis持久化以及高可用
    1.发布订阅模式例子:比如说你有一个收音机,你收听了xxxx频道,那么只要你你打开这个频道,你就能听到这个频道的所有内容你的收音机----接收方(订阅方)频道的内容发送方---内......
  • P7712 [Ynoi2077] hlcpq 题解
    虚式优化建图题。首先有一个很显然的暴力,对于两条相交的线段连一条边,然后跑割点。这个暴力的问题在于边与点的时间复杂度相差过大,无论是空间还是时间都无法承受,所以可以......
  • Java Set Summary
    JavaSetSummary一、概要Set6个类名since线程安全elementnull特点Set1.2HashSet1.2NoYes基于HashMap实现TreeSet1.2NoNo基于TreeMa......
  • 路飞项目day_11 django中celery使用 轮播图实时 课程前端 功能表
    目录今日内容详细一、celery执行异步任务、延迟任务、定时任务二、django中使用celery1.秒杀功能1.1视图1.2任务order_task.py1.3前端2.django中使用celery三、轮播图接口......
  • centos stream9 源码安装 amule 2.3.3
    下载amule源码cdaMule-2.3.3mkdirbuild-kuncdbuild-kun../configure缺少依赖zlibsudodnfinstallzlib-devel重复执行../configure缺少wxwidgets从源代码......
  • Python迭代与生成器
    1、迭代_iter_对象方法可迭代对象,返回迭代器__next_对象方法迭代器对象,返回迭代中每一步的运算iter(object)内置函数得到object的迭代器next(object)......
  • 如何学好计算机网络的方法?
     我觉得正确的学习方法应该是边学理论边动手实践。动手包括两类方法:                  一类是用一些命令行工具进行观测,另外一类......
  • [java-project-gl]接口幂等性
    接口幂等性一、什么是幂等性接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用;比如说支付场景,用户购买了商品支......