zoukankan      html  css  js  c++  java
  • __slots__节约空间

    1.为什么要使用__slots__

    Python 使用 dicts(hash table)缓存大量的静态资源(属性)。

    我们最近在Image类中,用仅仅一行__slots__代码,改变成使用tuple储存,可以节约大量内存空间。

    为啥呢?

    和list相比,dict 查找和插入的速度极快,不会随着key的增加而增加;dict需要占用大量的内存,内存浪费多。

    而list查找和插入的时间随着元素的增加而增加;占用空间小,浪费的内存很少。

    python解释器是Cpython,这两个数据结构应该对应C的哈希表和数组。因为哈希表需要额外内存记录映射关系,而数组只需要通过索引就能计算出下一个节点的位置,所以哈希表占用的内存比数组大,也就是dict比list占用的内存更大。

    2.默认情况

    默认情况下,Python用一个dict来存储对象实例的属性。这在一般情况下还不错,而且非常灵活,乃至你在运行时可以随意设置新的属性。

    但是,对一些在”编译”前就知道该有几个固定属性的小class来说,这个dict就有点浪费内存了。而当你把这个小浪费乘上一百万,那可就大不同了。

    在Python中,你可以在class中设置__slots__,它是一个包含这些固定的属性名的list。这样Python就不会再使用dict,而且只分配这些属性的空间。

    默认情况下:

    改成__slots__后:

    class Image(object):
        __slots__ = ['id', 'name', 'age']
     
        def __init__(self, id, name, age):
            self.id = id
            self.name = name
            self.age = age
            
            
            
    i=Image(1,'wqbin',18)
    i.__dict__

    你还可以用collections.namedtuple,它允许访问参数,但只占用一个tuple的空间。这跟__slots__类似。不过我总觉得继承一个namedtuple类很奇怪。另外,如果你需要自定义初始化,你应该重载__new__而不是__init__。

    警告:不要贸然进行这个优化,把它用在所有地方。这种做法不利于代码维护,而且只有当你有数以千计的实例的时候才会有明显效果。

    译注:作者在评论中关于”不利于代码维护“的说法:

    webreac:我觉得__slots__关键字不只是速度优化(注:这里应该是内存优化),也是类字段名的一个可靠”文档“。这有利于代码维护。为什么你觉得它不好?

    Ben Hoyt(作者):有趣的说法——我不确定应不应该把__slots__作为文档。不过的确是不错的注意。我之前这么说的原因是,你需要对字段名”定义“两次(不够DRY)。namedtuple也类似

     3.空间节省效果

    如何查看内存占用

    class Foobar(object):
        __slots__=('x')
        def __init__(self, x):
            self.x = x
     
    @profile
    def main():
        f = [Foobar(42) for i in range(1000000)]
     
    if __name__ == "__main__":
        main()

    class Foobar(object):
        def __init__(self, x):
            self.x = x
     
    @profile
    def main():
        f = [Foobar(42) for i in range(1000000)]
     
    if __name__ == "__main__":
        main()

     

    100百万个实例化对象的内存占用从208M降低到93M

  • 相关阅读:
    Java实现连接FTP服务并传递文件
    消息队列(MQ)入门-activemq,rocketmq代码级别
    js分页功能实现
    记录几个遇到的问题和解决方法
    oracle 日志归档设置
    打印系统时间
    linux 定时任务
    linux 安装jdk
    db2 命令
    二维码、条形码扫描——使用Google ZXing
  • 原文地址:https://www.cnblogs.com/wqbin/p/10394590.html
Copyright © 2011-2022 走看看