爱上python系列------python性能(八):__slots__减少内存的使用

__slots__用于固定class里面打属性,一旦使用了__slots__,就只能使用设置好的属性了,而不能动态添加了

没有使用__slots__的class,实例化对象的是时候是使用的dict,而使用过的会将dict转成一个元组,我们都知道元组是不能修改的。有利于检索对象,因此加上__slots__的类,无需分配和使用dict

接下来,我们做一个实验,对比加上和没有加上的对象使用字节数量

使用__slots__

from pympler.asizeof import asizesof

class DaGongRen():#打工人
    __slots__ = ('id_dg','age','salary')
    def __init__(self,id_dg,age,salary):
        self.id_dg=id_dg
        self.age=age
	self.salary=salary

    #@profile
    def test():
        d=DaGongRen(10001,18,2000)
	#print(asizesof(d.__dict__))
        print(asizesof(d))
if __name__ == '__main__':
    test()

运行结果:

[aspiree1431 opt]# python  lru_cache.py
(152,)

不使用__slots__:

from pympler.asizeof import asizesof

class DaGongRen():#打工人
    #__slots__ = ('id_dg','age','salary')
    def __init__(self,id_dg,age,salary):
        self.id_dg=id_dg
        self.age=age
	self.salary=salary

    #@profile
    def test():
        d=DaGongRen(10001,18,2000)
	#print(asizesof(d.__dict__))
        print(asizesof(d))
if __name__ == '__main__':
    test()

运行结果:

[aspiree1431 opt]# python  lru_cache.py
(416,)

我们可以看到,使用__slots__后对象内存使用减少还是比较多

上面只是显示的是对象使用的内存,接下来准备对比一下使用__slots__后函数内存使用的情况:

使用__slots__:

from pympler.asizeof import asizesof

class DaGongRen():#打工人
    __slots__ = ('id_dg','age','salary')
    def __init__(self,id_dg,age,salary):
	self.id_dg=id_dg
	self.age=age
	self.salary=salary

    @profile
    def test():
	d=[ DaGongRen(10001,18,2000) for i in range(100000) ]
	#print(asizesof(d.__dict__))
	#print(asizesof(d))
if __name__ == '__main__':
    test()

运行结果:

[aspiree1431 opt]# python -m memory_profiler lru_cache.py 
Filename: lru_cache.py

Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
    32   33.656 MiB   33.656 MiB           1   @profile
    33                                         def test():
    34   40.809 MiB    7.152 MiB      100003            d=[ DaGongRen(10001,18,2000) for i in range(100000) ]

不使用__slots__:

from pympler.asizeof import asizesof

class DaGongRen():#打工人
    #__slots__ = ('id_dg','age','salary')
    def __init__(self,id_dg,age,salary):
	self.id_dg=id_dg
	self.age=age
	self.salary=salary

    @profile
    def test():
	d=[ DaGongRen(10001,18,2000) for i in range(100000) ]
	#print(asizesof(d.__dict__))
	#print(asizesof(d))
if __name__ == '__main__':
    test()

运行结果:

[aspiree1431 opt]# python -m memory_profiler lru_cache.py 
Filename: lru_cache.py

Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
    32   33.926 MiB   33.926 MiB           1   @profile
    33                                         def test():
    34   50.301 MiB   16.375 MiB      100003            d=[ DaGongRen(10001,18,2000) for i in range(100000) ]

我们可以发现,减少还是很多,不过好像看起来没有上面只是对象的时候比例高,这是因为对象只是函数里面的一部分,举个简单的例子。假如A有两个炒股账户A1+A2,A1基本上保持不变动,但是是占比最高,达到90%,而A2需要调整,但是占比10%,现在市场行情很好,A2翻了3倍,但是A的总账户能够翻3倍吗?

因此,我们在来做一个实验,减少迭代次数,然后会发现使用__slots__和不使用__slots__没啥区别

具体操作就是将上面的代码了里面的range(100000)里面减少一个0

#这个是使用了的
[aspiree1431 opt]# python -m memory_profiler lru_cache.py 
Filename: lru_cache.py

Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
    32   33.129 MiB   33.129 MiB           1   @profile
    33                                         def test():
    34   33.129 MiB    0.000 MiB           1            d=DaGongRen(2,18,2000)

#这个是没有使用了的
[aspiree1431 opt]# python -m memory_profiler lru_cache.py 
Filename: lru_cache.py

Line #    Mem usage    Increment  Occurences   Line Contents
============================================================
    32   33.344 MiB   33.344 MiB           1   @profile
    33                                         def test():
    34   33.344 MiB    0.000 MiB           1            d=DaGongRen(2,18,2000)

这个实验可以说明,建对象需要很多的时候才能提升比较大,对于函数而已

猜你喜欢

转载自blog.csdn.net/zhou_438/article/details/109276710