详解python 内存优化
作者:Rocky0429 发布时间:2022-06-04 16:31:43
写在之前
围绕类的话题,说是说不完的,仅在特殊方法,除了我们在前面遇到过的 __init__(),__new__(),__str__() 等之外还有很多。虽然它们只是在某些特殊的场景中才会用到,但是学会它们却可以成为你熟悉这门语言路上的铺路石。
所以我会在试图介绍一些「黑魔法」,让大家多多感受一下 Python 的魅力所在,俗话说「艺多不压身」就是这个道理了。
内存优化
首先先让我们从复习前面的类属性和实例属性的知识来引出另一个特殊方法:
>>> class Sample:
... name = 'rocky'
...
就像前面的文章我们所说的,每个类都有一个 __dict__() 属性,它包含了当前类的类属性:
>>> Sample.__dict__
mappingproxy({'__module__': '__main__', 'name': 'rocky', '__dict__': <attribute '__dict__' of 'Sample' objects>, '__weakref__': <attribute '__weakref__' of 'Sample' objects>, '__doc__': None})
>>> Sample.name
'rocky'
同样,如果我们创建了实例,每个实例也有一个 __dict__ 属性,它里面就是当前的实例属性:
>>> a = Sample()
>>> a.__dict__
{}
>>> a.age = 23
>>> a.__dict__
{'age': 23}
上面的操作可以看出,当实例刚刚创建的时候,__dict__ 是空的,只有创建了实例属性以后,它才包含其内容。实例的 __dict__ 和类的 __dict__ 是有所区别的,即实例属性和类属性是不同的。
从理论上来说,我们可以根据一个类创建无数的实例,新建一个实例以后,又创建了一个新的 __dict__,这将是一个很可怕的事情,虽然每个 __dict__ 所占的内存空间很小,当然这件事事实上是不会出现的。但是程序不能建立在这种不可靠的猜测的基础上,程序要对过程有明确的控制。
所以就要有一种方法能够控制 __dict__,于是「__slots__」应运而生。
>>> class Nature:
... __slots__ = ('tree','flower')
...
>>> dir(Nature)
['__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__', 'flower', 'tree']
我们仔细来看 dir() 的结果,发现 __dict__ 属性没有了,也就是说 __slots__ 把 __dict__ 挤出去了,它进入了类的属性。
>>> Nature.__slots__
('tree', 'flower')
从这里可以看出,类 Nature 有且仅有两个属性。从类的角度来看,其类属性只有这两个;从实例的角度来看,其实例属性也只有这两个。
>>> Nature.tree = 'liushu'
>>> Nature.tree
'liushu'
>>> Nature.tree = 'lishu'
>>> Nature.tree
'lishu'
通过类可以对属性进行赋值和修改,这个似乎和以前的类属性没有什么区别,别着急,继续往下看就看到区别了:
>>> x = Nature()
>>> x.__slots__
('tree', 'flower')
>>> y = Nature()
>>> y.__slots__
('tree', 'flower')
>>> id(x.__slots__)
4531629384
>>> id(y.__slots__)
4531629384
你看,实例化以后,实例的 __slots__ 和类的 __slots__ 完全一样,这跟前面的 __dict__ 大不一样了。并且我们建立了两个实例,结果发现两个实例的 __slots__ 在内存中居然是一个,或者可以说是增加实例时 __slots__ 并不增加。
>>> x.tree
'lishu'
>>> y.tree
'lishu'
既然类属性已经赋值,那么通过任何一个实例属性都能得到同样的值,不过这时候不能通过实例修改此属性的值。
>>> x.tree = 'taoshu'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Nature' object attribute 'tree' is read-only
对实例属性来说,类的静态数据是只读的,不能修改,只有通过类属性才能修改。但对于尚未赋值的属性,能够通过实例赋值。
>>> x.flower = 'rose'
>>> x.flower
'rose'
>>> x.flower = 'moli'
显然通过实例操作的属性,也能够通过实例修改,但是实例属性的值并不能够修改类属性的值
Nature.flower
<member 'flower' of 'Nature' objects>
由上面可以看出,实例属性的值并没有传回给类属性,也可以理解为新建了一个同名字的实例属性,如果再给类属性赋值的话,则会像下面一样:
>>> Nature.flower = 'huaihua'
>>> x.flower
'huaihua'
类属性对实例属性具有决定作用,对实例而言,通过类所定义的属性都是只读的。
__slots__ 已经把实例属性牢牢的看管起来,只能是指定的属性,如果想要增加属性的话,只能通过类属性来实现,所以 __slots__ 的一个重要作用就是优化了内存。
写在之后
当然了,__slots__ 还能加快属性加载速度,这个不是本文的重点,所以不做过多的介绍,感兴趣的可以去 Google 一下。
今天的文章就到这里啦,明天讲一下「属性拦截」,又是新的一周,燥起来!
如果你觉得文章对你有帮助的话,欢迎点赞转发,让更多的人看到,谢谢啦。
The end。
来源:https://cloud.tencent.com/developer/article/1534437


猜你喜欢
- @click @tap重叠事件区分点击remove事件会触发details事件,使用@click.stop官方介绍<ul>??
- 今天用scrapy爬取壁纸的时候(url:http://pic.netbian.com/4kmein...)絮叨了一些问题,记录下来,供后世
- 现在我们已经很熟悉Django的MTV模式了。模板(template)负责如何去展示数据,而视图(view)负责筛选出正确的数据。因此通常来
- @using@using 指令用于向生成的视图添加 C# using 指令:@using System.IO@{
- 前言在编程开发中,个人觉得,只要按照规范去做,很少会出问题。刚开始学习一门技术时,的确会遇到很多的坑。踩的坑多了,这是好事,会学到更多东西,
- 英文文档:class type(object)class type(name, bases, dict)With one argument,
- 概述数据库中的数据直接呈现出来一般不是我们想要的,所以我们上两节演示了如何对数据进行过滤的方法。除了对数据进行过滤,我们可能还需要对数据进行
- 本次转换需要依赖使用工具Navicat Premium。首先,将数据库移至本地SQLServer,我试过直接在局域网上其他SQLServer
- 这篇文章主要介绍Python的numpy库中的一些函数,做备份,以便查找。(1)将矩阵转换为列表的函数:numpy.matrix.tolis
- 楔子shutil 是一个 Python 内置模块,该模块对文件的复制、删除和压缩等操作都提供了非常方便的支持。下面来详细介绍一下该模块的用法
- 大家好,今天跟大家分享一个用Python实现的学生学籍管理系统:该代码主体由五个函数组成:1.add_stu() 添加2.del_stu()
- 通过上篇文章给大家介绍了SqlServer应用之sys.dm_os_waiting_tasks 引发的疑问(上) ,说了一下sys.dm_e
- 判断缩进代替大括号。冒号(:)后换号缩进。iftest=100if test>50: print('OK')print
- Pandas是Python中最流行的数据分析和处理工具之一,它提供了一个名为DataFrame的数据结构,可以被认为是一个二维表格或电子表格
- 本文实例讲述了Python实现将数据框数据写入mongodb及mysql数据库的方法。分享给大家供大家参考,具体如下:主要内容:1、数据框数
- python的开发工具有很多种,各有特点,本人一直使用的是pycharm,所以本篇内容仅限pycharm。1,设置python文件头模板当我
- 一、准备工程文件1.创建工程leeoo2.在工程根目录下创建setup.py文件3.在工程根目录下创建同名package二、编辑setup.
- 一开始我使用了rarfile这个库,奈何对于含有密码的压缩包支持不好,在linux上不抛出异常;之后有又尝试了unrar。。比rarfile
- 引言最近再做图像处理相关的操作的时间优化,用到了OpenCV和Pillow两个库,两个库各有优缺点。各位小伙伴需要按照自己需求选用。本篇博客
- 前言还记得这个九九乘法表吗,这次课后相信你可以用代码给你的小弟弟妹妹们变出这份“葵花宝典”。循环如果要把循环翻译成机器语言,那他对应的可以是