Python中的__slots__示例詳解
前言
相信Python老鳥都應該看過那篇非常有吸引力的Saving 9 GB of RAM with Python's slots 文章,作者使用了__slots__讓內存占用從25.5GB降到了16.2GB。在當時來說,這相當于用一個非常簡單的方式就降低了30%的內存使用,著實驚人。作者并沒有提到他的業(yè)務特點和代碼,那我們就基于《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個實例這種機會非常少見,用不用完全根據業(yè)務來決定,并不要以偏概全。因為(敲黑板了哈)使用__slots__也是有副作用的:
- 每個繼承的子類都要重新定義一遍__slots__
- 實例只能包含哪些在__slots__定義的屬性,這對寫程序的靈活性有影響,比如你由于某個原因新網給instance設置一個新的屬性,比如instance.a = 1, 但是由于a不在__slots__里面就直接報錯了,你得不斷地去修改__slots__或者用其他方法迂回的解決
- 實例不能有弱引用(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中l(wèi)ambda的用法及其與def的區(qū)別解析
這篇文章主要介紹了Python中l(wèi)ambda的用法及其與def的區(qū)別解析,需要的朋友可以參考下2014-07-07

