8.4 創(chuàng)建大量對象時節(jié)省內(nèi)存方法

2018-02-24 15:26 更新

問題

你的程序要創(chuàng)建大量(可能上百萬)的對象,導(dǎo)致占用很大的內(nèi)存。

解決方案

對于主要是用來當成簡單的數(shù)據(jù)結(jié)構(gòu)的類而言,你可以通過給類添加 __slots__ 屬性來極大的減少實例所占的內(nèi)存。比如:

class Date:
    __slots__ = ['year', 'month', 'day']
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

當你定義 __slots__ 后,Python就會為實例使用一種更加緊湊的內(nèi)部表示。實例通過一個很小的固定大小的數(shù)組來構(gòu)建,而不是為每個實例定義一個字典,這跟元組或列表很類似。在 __slots__ 中列出的屬性名在內(nèi)部被映射到這個數(shù)組的指定小標上。使用slots一個不好的地方就是我們不能再給實例添加新的屬性了,只能使用在 __slots__ 中定義的那些屬性名。

討論

使用slots后節(jié)省的內(nèi)存會跟存儲屬性的數(shù)量和類型有關(guān)。不過,一般來講,使用到的內(nèi)存總量和將數(shù)據(jù)存儲在一個元組中差不多。為了給你一個直觀認識,假設(shè)你不使用slots直接存儲一個Date實例,在64位的Python上面要占用428字節(jié),而如果使用了slots,內(nèi)存占用下降到156字節(jié)。如果程序中需要同時創(chuàng)建大量的日期實例,那么這個就能極大的減小內(nèi)存使用量了。

盡管slots看上去是一個很有用的特性,很多時候你還是得減少對它的使用沖動。Python的很多特性都依賴于普通的基于字典的實現(xiàn)。另外,定義了slots后的類不再支持一些普通類特性了,比如多繼承。大多數(shù)情況下,你應(yīng)該只在那些經(jīng)常被使用到的用作數(shù)據(jù)結(jié)構(gòu)的類上定義slots(比如在程序中需要創(chuàng)建某個類的幾百萬個實例對象)。

關(guān)于 __slots__ 的一個常見誤區(qū)是它可以作為一個封裝工具來防止用戶給實例增加新的屬性。盡管使用slots可以達到這樣的目的,但是這個并不是它的初衷。__slots__ 更多的是用來作為一個內(nèi)存優(yōu)化工具。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號