Python __slots__ 详解
Python老鸟都应该看过那篇非常有吸引力的 Saving 9 GB of RAM with Python’s slots__ 文章,作者使用了__slots让内存占用从25.5GB降到了16.2GB。在当时来说,这相当于用一个非常简单的方式就降低了30%的内存使用,着实惊人。作者并没有提到他的业务特点和代码,那我们就基于《fluent python》中的例子来验证下是不是有这么厉害:
from __future__ import print_function import resource class A(object): def __init__(self): self.a = 'string' self.b = 10 self.c = True class B(object): __slots__ = ['a', 'b', 'c'] def __init__(self): self.a = 'string' self.b = 10 self.c = True def test(cls): mem_init = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss l = [] for i in range(500000): l.append(cls()) mem_final = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss del l print('Class: {}:\n'.format(getattr(cls, '__name__'))) print('Initial RAM usage: {:14,}'.format(mem_init)) print(' Final RAM usage: {:14,}'.format(mem_final)) print('-' * 20) if __name__ == '__main__': import sys test(globals()[sys.argv[1].upper()])
我们分别跑一下这2个类:
❯ python mem_test.py a Class: A: Initial RAM usage: 4,890,624 Final RAM usage: 200,454,144 -------------------- ❯ python mem_test.py b Class: B: Initial RAM usage: 4,919,296 Final RAM usage: 60,235,776
2种方法初始内存略有差别,但是由于这个差别和总内存量相比太小而忽略不计,结论就是:
使用slots可以让内存使用减少3.5倍!!# 通过 (200 – 4) / ((60 – 4) * 1.0) 计算得来
那么用slot就是非非常那个有必要吗?事实上500000个实例这种机会非常少见,用不用完全根据业务来决定,并不要以偏概全。因为(敲黑板了哈)使用slots也是有副作用的:
1. 每个继承的子类都要重新定义一遍__slots__ 2. 实例只能包含哪些在__slots__定义的属性,这对写程序的灵活性有影响,比如你由于某个原因新网给instance设置一个新的属性,比如instance.a = 1, 但是由于a不在__slots__里面就直接报错了,你得不断地去修改__slots__或者用其他方法迂回的解决 3. 实例不能有弱引用(weakref)目标,否则要记得把__weakref__放进__slots__
第三点有点难理解,我写个例子看看吧:
In [2]: %pycat ref_example.py from weakref import ref class A(object): __slots__ = ['b'] def __init__(self): self.b = 1 class B(object): __slots__ = ['b', '__weakref__'] def __init__(self): self.b = 1 In [3]: from ref_example import * In [4]: a = A() In [5]: r = ref(a) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-6-75a6d689c8b3> in <module>() ----> 1 r = ref(a) TypeError: cannot create weak reference to 'A' object In [6]: b = B() In [7]: r = ref(b) In [8]: r Out[8]: <weakref at 0x109199578; to 'B' at 0x10919f890>
所以实例不超过万级别的类,slots是不太值得使用的。
PS:《fluent python》比我狠,说的是小于百万级别实例不值得使用。
无耻的广告:《Python Web开发实战》上市了!
欢迎关注本人的微信公众号获取更多Python相关的内容(也可以直接搜索「Python之美」)
相关推荐
-
php 学习笔记之关于时区的那点事 python基础
2019-6-1
-
爬虫爬 JSON HTML 数据 python基础
2019-6-22
-
Python第六章-函数02-函数的作用域 python基础
2020-6-11
-
Python程序每日一练习 python基础
2019-7-21
-
Django快速入门 python基础
2019-10-9
-
基于Python通过MQTT协议连接OneNet简例 python基础
2020-5-31
-
Python | 浅拷贝 | 深拷贝 python基础
2019-10-10
-
Python爬虫图形界面封装版本 python基础
2019-8-28
-
5个python顶级web框架 python基础
2019-10-10
-
用贝叶斯判别分析再次预测股票涨跌情况 python基础
2019-8-26