最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python使用__slots__讓你的代碼更加節(jié)省內(nèi)存

 更新時間:2018年09月05日 09:10:01   作者:david_bj  
如果要限制添加的屬性,例如,Student類只允許添加 name、gender和score 這3個屬性,就可以利用Python的一個特殊的slots來實現(xiàn)。這篇文章主要給大家介紹了關(guān)于python如何使用__slots__讓你的代碼更加節(jié)省內(nèi)存的相關(guān)資料,需要的朋友可以參考下

前言

在默認(rèn)情況下,Python的新類和舊類的實例都有一個字典來存儲屬性值。這對于那些沒有實例屬性的對象來說太浪費(fèi)空間了,當(dāng)需要創(chuàng)建大量實例的時候,這個問題變得尤為突出。

因此這種默認(rèn)的做法可以通過在新式類中定義了一個__slots__屬性從而得到了解決。__slots__聲明中包含若干實例變量,并為每個實例預(yù)留恰好足夠的空間來保存每個變量,因此沒有為每個實例都創(chuàng)建一個字典,從而節(jié)省空間。

本文主要介紹了關(guān)于python使用__slots__讓你的代碼更加節(jié)省內(nèi)存的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧

現(xiàn)在來說說python中dict為什么比list浪費(fèi)內(nèi)存?

和list相比,dict 查找和插入的速度極快,不會隨著key的增加而增加;dict需要占用大量的內(nèi)存,內(nèi)存浪費(fèi)多。

而list查找和插入的時間隨著元素的增加而增加;占用空間小,浪費(fèi)的內(nèi)存很少。

python解釋器是Cpython,這兩個數(shù)據(jù)結(jié)構(gòu)應(yīng)該對應(yīng)C的哈希表和數(shù)組。因為哈希表需要額外內(nèi)存記錄映射關(guān)系,而數(shù)組只需要通過索引就能計算出下一個節(jié)點的位置,所以哈希表占用的內(nèi)存比數(shù)組大,也就是dict比list占用的內(nèi)存更大。

如果想更加詳細(xì)了解,可以查看C的源代碼。python官方鏈接:https://www.python.org/downloads/source/

如下代碼是我從python官方截取的代碼片段:

List 源碼:

typedef struct {
 PyObject_VAR_HEAD
 /* Vector of pointers to list elements. list[0] is ob_item[0], etc. */
 PyObject **ob_item;
 
 /* ob_item contains space for 'allocated' elements. The number
 * currently in use is ob_size.
 * Invariants:
 * 0 <= ob_size <= allocated
 * len(list) == ob_size
 * ob_item == NULL implies ob_size == allocated == 0
 * list.sort() temporarily sets allocated to -1 to detect mutations.
 *
 * Items must normally not be NULL, except during construction when
 * the list is not yet visible outside the function that builds it.
 */
 Py_ssize_t allocated;
} PyListObject;

Dict源碼:

/* PyDict_MINSIZE is the minimum size of a dictionary. This many slots are
 * allocated directly in the dict object (in the ma_smalltable member).
 * It must be a power of 2, and at least 4. 8 allows dicts with no more
 * than 5 active entries to live in ma_smalltable (and so avoid an
 * additional malloc); instrumentation suggested this suffices for the
 * majority of dicts (consisting mostly of usually-small instance dicts and
 * usually-small dicts created to pass keyword arguments).
 */
#define PyDict_MINSIZE 8
 
typedef struct {
 /* Cached hash code of me_key. Note that hash codes are C longs.
 * We have to use Py_ssize_t instead because dict_popitem() abuses
 * me_hash to hold a search finger.
 */
 Py_ssize_t me_hash;
 PyObject *me_key;
 PyObject *me_value;
} PyDictEntry;
 
/*
To ensure the lookup algorithm terminates, there must be at least one Unused
slot (NULL key) in the table.
The value ma_fill is the number of non-NULL keys (sum of Active and Dummy);
ma_used is the number of non-NULL, non-dummy keys (== the number of non-NULL
values == the number of Active items).
To avoid slowing down lookups on a near-full table, we resize the table when
it's two-thirds full.
*/
typedef struct _dictobject PyDictObject;
struct _dictobject {
 PyObject_HEAD
 Py_ssize_t ma_fill; /* # Active + # Dummy */
 Py_ssize_t ma_used; /* # Active */
 
 /* The table contains ma_mask + 1 slots, and that's a power of 2.
 * We store the mask instead of the size because the mask is more
 * frequently needed.
 */
 Py_ssize_t ma_mask;
 
 /* ma_table points to ma_smalltable for small tables, else to
 * additional malloc'ed memory. ma_table is never NULL! This rule
 * saves repeated runtime null-tests in the workhorse getitem and
 * setitem calls.
 */
 PyDictEntry *ma_table;
 PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
 PyDictEntry ma_smalltable[PyDict_MINSIZE];
};

PyObject_HEAD 源碼:

#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA  \
 struct _object *_ob_next;  \
 struct _object *_ob_prev;
 
#define _PyObject_EXTRA_INIT 0, 0,
 
#else
#define _PyObject_HEAD_EXTRA
#define _PyObject_EXTRA_INIT
#endif
 
/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD   \
 _PyObject_HEAD_EXTRA  \
 Py_ssize_t ob_refcnt;  \
 struct _typeobject *ob_type;

PyObject_VAR_HEAD 源碼:

/* PyObject_VAR_HEAD defines the initial segment of all variable-size
 * container objects. These end with a declaration of an array with 1
 * element, but enough space is malloc'ed so that the array actually
 * has room for ob_size elements. Note that ob_size is an element count,
 * not necessarily a byte count.
 */
#define PyObject_VAR_HEAD  \
 PyObject_HEAD   \
 Py_ssize_t ob_size; /* Number of items in variable part */

現(xiàn)在知道了dict為什么比list 占用的內(nèi)存空間更大。接下來如何讓你的類更加的節(jié)省內(nèi)存。

其實有兩種解決方案:

第一種是使用__slots__ ;另外一種是使用Collection.namedtuple 實現(xiàn)。

首先用標(biāo)準(zhǔn)的方式寫一個類:

#!/usr/bin/env python

class Foobar(object):
 def __init__(self, x):
 self.x = x

@profile
def main():
 f = [Foobar(42) for i in range(1000000)]

if __name__ == "__main__":
 main()

然后,創(chuàng)建一個類Foobar(),然后實例化100W次。通過@profile查看內(nèi)存使用情況。

運(yùn)行結(jié)果:

該代碼共使用了372M內(nèi)存。

接下來通過__slots__代碼實現(xiàn)該代碼:

#!/usr/bin/env python

class Foobar(object):
 __slots__ = 'x'
 def __init__(self, x):
 self.x = x
@profile
def main():
 f = [Foobar(42) for i in range(1000000)]

if __name__ == "__main__":
 main()

運(yùn)行結(jié)果:

使用__slots__使用了91M內(nèi)存,比使用__dict__存儲屬性值節(jié)省了4倍。

其實使用collection模塊的namedtuple也可以實現(xiàn)__slots__相同的功能。namedtuple其實就是繼承自tuple,同時也因為__slots__的值被設(shè)置成了一個空tuple以避免創(chuàng)建__dict__。

看看collection是如何實現(xiàn)的:

collection 和普通創(chuàng)建類方式相比,也節(jié)省了不少的內(nèi)存。所在在確定類的屬性值固定的情況下,可以使用__slots__方式對內(nèi)存進(jìn)行優(yōu)化。但是這項技術(shù)不應(yīng)該被濫用于靜態(tài)類或者其他類似場合,那不是python程序的精神所在。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • tensorflow 實現(xiàn)從checkpoint中獲取graph信息

    tensorflow 實現(xiàn)從checkpoint中獲取graph信息

    今天小編就為大家分享一篇tensorflow 實現(xiàn)從checkpoint中獲取graph信息,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Linux永久修改pip配置源的詳細(xì)過程

    Linux永久修改pip配置源的詳細(xì)過程

    默認(rèn)情況下pip使用的是國外的鏡像,在下載的時候速度非常慢,所以需要更換PIP的鏡像源,下面這篇文章主要給大家介紹了關(guān)于Linux永久修改pip配置源的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • python使用百度或高德地圖獲取地理位置并轉(zhuǎn)換

    python使用百度或高德地圖獲取地理位置并轉(zhuǎn)換

    用python處理地理位置是非常常見的需求,下面這篇文章主要給大家介紹了關(guān)于python使用百度或高德地圖獲取地理位置并轉(zhuǎn)換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Python科學(xué)計算之NumPy入門教程

    Python科學(xué)計算之NumPy入門教程

    這篇文章主要介紹了Python科學(xué)計算之NumPy,文中給出了詳細(xì)的介紹與示例代碼,對大家的理解具有一定的參考借鑒價值,有需要的朋友可以一起來學(xué)習(xí)學(xué)習(xí)。
    2017-01-01
  • Python機(jī)器學(xué)習(xí)庫Scikit-learn實戰(zhàn)教程

    Python機(jī)器學(xué)習(xí)庫Scikit-learn實戰(zhàn)教程

    文章介紹了Python在機(jī)器學(xué)習(xí)領(lǐng)域的應(yīng)用,重點介紹了Scikit-learn庫的使用方法,并通過實際案例展示了如何使用Scikit-learn進(jìn)行分類、回歸、聚類和文本挖掘等任務(wù),同時,文章還討論了特征工程、超參數(shù)調(diào)整、避免過擬合和交叉驗證等進(jìn)階技巧
    2025-01-01
  • 教你怎么用Python實現(xiàn)GIF動圖的提取及合成

    教你怎么用Python實現(xiàn)GIF動圖的提取及合成

    今天教大家一個Python有趣好玩的小功能:將多張圖片轉(zhuǎn)為GIF,同時也可以將一個GIF動圖提取出里面的圖片,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Python學(xué)習(xí)筆記基本數(shù)據(jù)結(jié)構(gòu)之序列類型list tuple range用法分析

    Python學(xué)習(xí)筆記基本數(shù)據(jù)結(jié)構(gòu)之序列類型list tuple range用法分析

    這篇文章主要介紹了Python學(xué)習(xí)筆記基本數(shù)據(jù)結(jié)構(gòu)之序列類型list tuple range用法,結(jié)合具體實例形式分析了Python序列類型list tuple range基本概念、定義與使用技巧,需要的朋友可以參考下
    2019-06-06
  • 深入了解Python的異常處理機(jī)制

    深入了解Python的異常處理機(jī)制

    這篇文章主要為大家介紹了Python的異常處理機(jī)制,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • 利用python庫matplotlib繪制不同的圖表

    利用python庫matplotlib繪制不同的圖表

    這篇文章主要介紹了利用python庫matplotlib繪制不同的圖表,使用python中的matplotlib繪制圖表,主要分享繪制簡單的曲線圖、單條曲線圖、多條曲線圖、直方圖以及散點圖的思路和用法,需要的朋友可以參考一下
    2022-03-03
  • 全面了解python字符串和字典

    全面了解python字符串和字典

    下面小編就為大家?guī)硪黄媪私鈖ython字符串和字典。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07

最新評論

平度市| 焦作市| 延川县| 冀州市| 公主岭市| 郧西县| 永修县| 都兰县| 水富县| 玉溪市| 锡林郭勒盟| 东山县| 扶风县| 邢台市| 贵溪市| 茶陵县| 同心县| 武川县| 绩溪县| 阳东县| 荔浦县| 宜兰市| 通州区| 柏乡县| 隆尧县| 新竹市| 博湖县| 蒙山县| 吴川市| 茂名市| 金华市| 太原市| 旬邑县| 黔江区| 义乌市| 彭水| 靖远县| 海林市| 门源| 金塔县| 睢宁县|