Python是一门动态语言,可以在运行过程中,修改实例的属性和增删方法。任何实例都包含一个字典__dict__,该字典保存了实例所有的属性和方法。Python也通过这个字典可以将任意属性绑定到实例上。

有时候在实例的生命周期中处于安全等考虑只能操作固定的属性,不想增加属性,可以通过__slots__来就可以定义一个集合,只有在这个集合中的属性才能被操作。

__slots__ 是一个类的属性,有三个功能:

  1. 实例不能访问或添加__slots__之外的属性
  2. 实例没有__dict__方法
  3. 节省内存,实例保存属性的结构从字典变成列表

不使用__solt__

class A():

    t = 30
def __init__(self,x,y):
self.x = x
self.y = y def fun():
pass a = A(100,10)
print(a.__dict__)
print(a.x)
print(a.y)
print(a.t)
>>>
{'x': 100, 'y': 10}
100
10
30

特点:

  1. 可以通过a.__dict__ 输出实例所有属性
  2. 类变量不在a.__dict__管理的范围中

使用__slots__

不能动态添加属性

class A():
__slots__=('x', "y")
def __init__(self,x,y):
self.x = x
self.y = y
a = A(100,10)
print(a.x)
print(a.y)
>>>
100
10
a.z = 200
>>>
Traceback (most recent call last):
File "solt_demo.py", line 64, in <module>
a.z = 200
AttributeError: 'A' object has no attribute 'z'

实例的__dict__属性不存在

print(a.__dict__)
Traceback (most recent call last):
File "solt_demo.py", line 64, in <module>
print(a.__dict__)
AttributeError: 'A' object has no attribute '__dict__'

类属性不受影响

class A():
__slots__=('x', "y")
def __init__(self,x,y):
self.x = x
self.y = y A.new = 300
print(A.new)

子类不具有__slots__属性

父类中有__slots__,子类继承父类时子类不具有__slots__属性,可以操作实例的属性。

class A():
__slots__=('x', "y")
def __init__(self,x,y):
self.x = x
self.y = y class B(A):
pass b = B(33,44)
print(b.x)
print(b.y) b.z = 55
print(b.z)
print(b.__dict__)

更节省内存

不使用__slots__

from  memory_profiler import profile

class A():
def __init__(self,x,y):
self.x = x
self.y = y @profile
def main():
object_list = [A(100,20) for i in range(100000)] if __name__=='__main__':
main()
(python3.8) ➜  sublime python -m memory_profiler slots_demo.py
Filename: slots_demo.py Line # Mem usage Increment Occurrences Line Contents
=============================================================
9 13.8 MiB 13.8 MiB 1 @profile
10 def main():
11 30.0 MiB 16.2 MiB 100003 object_list = [A(100,20) for i in range(100000)]

使用__slots__

from  memory_profiler import profile

class A():
__slots__ = ("x", "y")
def __init__(self,x,y):
self.x = x
self.y = y @profile
def main():
object_list = [A(100,20) for i in range(100000)] if __name__=='__main__':
main()
(python3.8) ➜  sublime python -m memory_profiler slots_demo.py
Filename: slots_demo.py Line # Mem usage Increment Occurrences Line Contents
=============================================================
10 13.4 MiB 13.4 MiB 1 @profile
11 def main():
12 18.9 MiB 4.1 MiB 100003 object_list = [A(100,20) for i in range(100000)]

从结果来看不定义__slots__增加了16.2MB,定义__slots__增加了4.1MB,所以有理由相信有__slots__节省四分之三的内存。

节省内存的原因:

普通类使用字典保存所有属性,定义了__slots__之后使用列表保存所有属性,减少了内存的使用(因为属性个数固定,所有可以使用有序数据的列表,列表相比字典减少了内存消耗)

注意:

但是节省只在创建大量实例时才能体现。

总结

定义__slots__属性之后的特点如下:

  1. 实例的__dict__属性不存在,节省一定内存
  2. 不可以给实例动态绑定属性,但类的属性不受影响
  3. 子类继承有__solts__的父类时,不拥有__solts__,也就是子类不受限制
  4. 节省内存

参考:

https://blog.csdn.net/sxingming/article/details/52892640

Python中节省内存的方法之一:__slots__属性的更多相关文章

  1. PySpark 的背后原理--在Driver端,通过Py4j实现在Python中调用Java的方法.pyspark.executor 端一个Executor上同时运行多少个Task,就会有多少个对应的pyspark.worker进程。

    PySpark 的背后原理 Spark主要是由Scala语言开发,为了方便和其他系统集成而不引入scala相关依赖,部分实现使用Java语言开发,例如External Shuffle Service等 ...

  2. Python 中的内存管理

    Python 中一切皆对象,这些对象的内存都是在运行时动态地在堆中进行分配的,就连 Python 虚拟机使用的栈也是在堆上模拟的.既然一切皆对象,那么在 Python 程序运行过程中对象的创建和释放就 ...

  3. python中List的sort方法的用法

    python列表排序 简单记一下python中List的sort方法(或者sorted内建函数)的用法. 关键字: python列表排序 python字典排序 sorted List的元素可以是各种东 ...

  4. 【转】python中List的sort方法(或者sorted内建函数)的用法

    原始出处:http://gaopenghigh.iteye.com/blog/1483864 python列表排序 简单记一下python中List的sort方法(或者sorted内建函数)的用法. ...

  5. 【转】关于python中re模块split方法的使用

    注:最近在研究文本处理,需要用到正则切割文本,所以收索到了这篇文章,很有用,谢谢原作者. 原址:http://blog.sciencenet.cn/blog-314114-775285.html 关于 ...

  6. 查看python中模块的所有方法

    查看python中模块的所有方法     安装的python模块,现将查看方法总结如下 一.CMD命令行下使用pydoc命令 在命令行下运行$ pydoc modules即可查看 二.在python交 ...

  7. python中requests库使用方法详解

    目录 python中requests库使用方法详解 官方文档 什么是Requests 安装Requests库 基本的GET请求 带参数的GET请求 解析json 添加headers 基本POST请求 ...

  8. 全面了解python中的类,对象,方法,属性

    全面了解python中的类,对象,方法,属性 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...

  9. python中列表元素连接方法join用法实例

    python中列表元素连接方法join用法实例 这篇文章主要介绍了python中列表元素连接方法join用法,实例分析了Python中join方法的使用技巧,非常具有实用价值,分享给大家供大家参考. ...

  10. python 中去除空格的方法

    python 中去除空格的方法: def trim(s): l=[] for i in s: if i!=' ': l.append(i) return ''.join(l) 其中可以使用下面的 '' ...

随机推荐

  1. 24. 从零用Rust编写正反向代理,细说HTTP行为中的几种定时器

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现 ...

  2. .NET快速对接极光消息推送

    什么是消息推送? 很多手机APP会不定时的给用户推送消息,例如一些新闻APP会给用户推送用户可能感兴趣的新闻,或者APP有更新了,会给用户推送是否选择更新的消息等等,这就是所谓的"消息推送& ...

  3. 京东广告研发近期入选国际顶会文章系列导读——CIKM 2023篇

    近年来,放眼业界广告推荐领域的算法获得了长足的发展,从几篇奠定基础的序列学习.大规模图学习.在线学习&增强学习.多模态推荐问题等起步,业内算法不断迭代发展并在学术和工业场景上取得不错的应用. ...

  4. Lucene和索引

    全文索引的原理: 是 扫描每个词 对每个词创建索引,指明这个词在文章出现的次数和位置 全文检索的流程:对 检索的对象(文章,文档,网页内容) 预先建立 文档域 和 索引域 ,在索引域会分词创建索引,然 ...

  5. cmd命令根据端口号杀进程

    1.根据端口查到进程pid netstat –ano|findstr 端口号 1 2.使用taskkill命令杀死进程 taskkill /pid pid 1 温馨提醒: 1.执行完第一步后,命令行显 ...

  6. ElasticSearch之cat pending tasks API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/pending_tasks?v=true&pretty" --cacert ...

  7. 【推荐】Helix的编程语言配置

    目录 编程语言 languages.toml 语言配置 探测文件类型 编程语言服务 为一个编程语言配置语言服务 Tree-sitter 语法配置 选择语法 编程语言 编程语言设置以及语言服务器设置位于 ...

  8. CSS3学习笔记-选择器

    在CSS中,选择器是一种指定一个或多个元素的方法.可以根据元素的类型.类.ID.属性等特征来选择元素.CSS3引入了很多新的选择 器,让我们可以更加灵活和精准地选择元素. 下面介绍一些常用的CSS3选 ...

  9. Ubuntu 终端如何分割多个窗口

    sudo apt-get install terminator 查看 ~/.config(隐藏文件夹 ctrl + h 即可看见) 下是否有 terminator 文件夹 如果没有手动创建一个 然后在 ...

  10. 开发篇1:使用原生api和Langchain调用大模型

    对大模型的调用通常有以下几种方式:方式一.大模型厂商都会定义http风格的请求接口,在代码中可以直接发起http请求调用:方式二.在开发环境中使用大模型厂商提供的api:方式三.使用开发框架Langc ...