• 使用__slots__节省python内存技巧


    __slots__作用

    __slots__有一个作用是:限制类实例绑定的属性,但是它有一个更重要的作用就是节省内存,当然更适用于数据量大的情况(万量级以上)。

    __slots__节省内存的原理

    class Measurement:
        def __init__(self, x, y, value):
            self.x = x
            self.y = y
            self.val = value
    
    m1 = Measurement(1, 2, "Happy")
    m2 = Measurement(7, 10, "Crazy")
    m2.other = True
    

    其实,对类的变量值进行初始化,底层是通过一个指针指向__dict__(里面包含潜在的字段名和字段值)。举个例子,上面的程序底层实现过程如下:

    我们也可以通过程序查看这一底层形式: ``` print(m1.__dict__) # {'x': 1, 'y': 2, 'val': 'Happy'} print(m2.__dict__) # {'x': 7, 'y': 10, 'other': True, 'val': 'Crazy'} ``` 这就是python自定义变量底层的一个基本实现。通过对这一底层理解,我们就会知道,如果我们的实例有数百万个,那么底层会有相应数百万个字典拥有相同的key值(知识value值不同),这时非常耗内存的,这时候__slots__就发挥它的作用了。

    通过__slots__,我们可以稍微调整一下类,以改变类中字段的存储方式,废弃原来那种耗费内存的1对1重复的字典分配方式。具体如下:

    class Measurement:
        __slots__ = ['x', 'y', 'val']
     
        def __init__(self, x, y, value):
            self.x = x
            self.y = y
            self.val = value
    

    这样我们底层的实现就会变为如下方式:

    我们可以看出,现在字段名是与Measurement类这个类型相关联,而不是原来的与相应的实例1对1的关联。而字段值与原来的方式无差别,因为毕竟各个实例的字段名一样,可以统一存放,而字段值并不都是一样,当然对于字段值也一样的我们也统一存储(因为底层字典都是与类这个类型关联,而不是与每个实例的__dict__关联)。但对于数据量庞大的情况(数百万级以上),能够非常显著的节省内存空间(25.5GB -> 16.2GB)。

    以上就是__slots__能够节省内存的原理,主要还是要搞清楚python的类变量初始化的底层操作是通过字典存储后相关联这一方式进行的,__slots__只是改变了字典key,value与实例相关联的方式,可以总结如下:

    • 默认变量实例化方法:底层实例和字典是一对一的关系

    • 加入__slots__后:底层实例和字典是多对一的关系(重复的部分)。

  • 相关阅读:
    nextSibling VS nextElementSibling
    线程实现连续启动停,并在某一时间段内运行
    线程:安全终止与重启
    监控知识体系
    后台服务变慢解决方案
    Java泛型类型擦除以及类型擦除带来的问题
    常见的 CSRF、XSS、sql注入、DDOS流量攻击
    Spring对象类型——单例和多例
    一次线上OOM过程的排查
    深入浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列
  • 原文地址:https://www.cnblogs.com/wujingqiao/p/9639585.html
Copyright © 2020-2023  润新知