1. 程式人生 > >使用__slots__節省python內存技巧

使用__slots__節省python內存技巧

自定義變量 程序 實例 self. 定義 image code 空間 而不是

__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的關聯。而字段值與原來的方式無差別,因為畢竟各個實例的字段名一樣,可以統一存放,而字段值不一樣,我們還得用1對1的形式存儲字段值。但對於數據量龐大的情況(數百萬級以上),節省重復的字段名存儲已經能夠非常顯著的節省內存空間了(25.5GB -> 16.2GB)。

以上就是__slots__能夠節省內存的原理,主要還是要搞清楚python的類變量初始化的底層操作是通過字典存儲後相關聯這一方式進行的,__slots__只是改變了字典key,value與實例相關聯的方式,可以總結如下:

  • 默認變量實例化方法:底層實例和字典是一對一的關系

  • 加入__slots__後:底層實例和字典中的value是一對一的關系,和字典中的key是多對一的關系。

使用__slots__節省python內存技巧