麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發(fā) > Python > 正文

詳解字符串在Python內部是如何省內存的

2024-09-09 19:03:41
字體:
來源:轉載
供稿:網友

起步

Python3 起,str 就采用了 Unicode 編碼(注意這里并不是 utf8 編碼,盡管 .py 文件默認編碼是 utf8 )。 每個標準 Unicode 字符占用 4 個字節(jié)。這對于內存來說,無疑是一種浪費。

Unicode 是表示了一種字符集,而為了傳輸方便,衍生出里如 utf8 , utf16 等編碼方案來節(jié)省存儲空間。Python內部存儲字符串也采用了類似的形式。

三種內部表示Unicode字符串

為了減少內存的消耗,Python使用了三種不同單位長度來表示字符串:

每個字符 1 個字節(jié)(Latin-1) 每個字符 2 個字節(jié)(UCS-2) 每個字符 4 個字節(jié)(UCS-4)

源碼中定義字符串結構體:

# Include/unicodeobject.htypedef uint32_t Py_UCS4;typedef uint16_t Py_UCS2;typedef uint8_t Py_UCS1;# Include/cpython/unicodeobject.htypedef struct {  PyCompactUnicodeObject _base;  union {    void *any;    Py_UCS1 *latin1;    Py_UCS2 *ucs2;    Py_UCS4 *ucs4;  } data;           /* Canonical, smallest-form Unicode buffer */} PyUnicodeObject;

如果字符串中所有字符都在 ascii 碼范圍內,那么就可以用占用 1 個字節(jié)的 Latin-1 編碼進行存儲。而如果字符串中存在了需要占用兩個字節(jié)(比如中文字符),那么整個字符串就將采用占用 2 個字節(jié) UCS-2 編碼進行存儲。

這點可以通過 sys.getsizeof 函數(shù)外部窺探來驗證這個結論:

如圖,存儲 'zh' 所需的存儲空間比 'z' 多 1 個字節(jié), h 在這里占了 1 個字節(jié);

存儲 'z中' 所需的存儲空間比 '中' 多了 2 個字節(jié),z 在這里占了 2 個字節(jié)。

大多數(shù)的自然語言采用 2 字節(jié)的編碼就夠了。但如果有一個 1G 的 ascii 文本加載到內存后,在文本中插入了一個 emoji 表情,那么字符串所需的空間將擴大到 4 倍,是不是很驚喜。

為什么內部不采用 utf8 進行編碼

最受歡迎的 Unicode 編碼方案,Python內部卻不使用它,為什么?

這里就得說下 utf8 編碼帶來的缺點。這種編碼方案每個字符的占用字節(jié)長度是變化的,這就導致了無法按所以隨機訪問單個字符,例如 string[n] (使用utf8編碼)則需要先統(tǒng)計前n個字符占用的字節(jié)長度。所以由 O(1) 變成了 O(n) ,這更無法讓人接受。

因此Python內部采用了定長的方式存儲字符串。

字符串駐留機制

另一個節(jié)省內存的方式就是將一些短小的字符串做成池,當程序要創(chuàng)建字符串對象前檢查池中是否有滿足的字符串。在內部中,僅包含下劃線(_)、字母 和 數(shù)字 的長度不高過 20 的字符串才能駐留。駐留是在代碼編譯期間進行的,代碼中的如下會進行駐留檢查:

空字符串 '' 及所有; 變量名; 參數(shù)名; 字符串常量(代碼中定義的所有字符串); 字典鍵; 屬性名稱;

駐留機制節(jié)省大量的重復字符串內存。在內部,字符串駐留池由一個全局的 dict 維護,該字段將字符串用作鍵:

void PyUnicode_InternInPlace(PyObject **p){  PyObject *s = *p;  PyObject *t;  if (s == NULL || !PyUnicode_Check(s))    return;  // 對PyUnicodeObjec進行類型和狀態(tài)檢查  if (!PyUnicode_CheckExact(s))    return;  if (PyUnicode_CHECK_INTERNED(s))    return;  // 創(chuàng)建intern機制的dict  if (interned == NULL) {    interned = PyDict_New();    if (interned == NULL) {      PyErr_Clear(); /* Don't leave an exception */      return;    }  }  // 對象是否存在于inter中  t = PyDict_SetDefault(interned, s, s);  // 存在, 調整引用計數(shù)  if (t != s) {    Py_INCREF(t);    Py_SETREF(*p, t);    return;  }  /* The two references in interned are not counted by refcnt.    The deallocator will take care of this */  Py_REFCNT(s) -= 2;  _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL;}
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 成人毛片视频在线播放 | 999精品久久久| 亚洲第五色综合网 | 成人一级视频 | 手机在线看片国产 | 久久久精品视频免费看 | 欧美日韩色片 | cosplay裸体福利写真 | 九九视频精品在线观看 | 在线免费观看毛片视频 | 亚洲精品在线观看网站 | 999久久久精品 | 欧美中文字幕一区二区 | 久久网一区二区 | 国产精品久久久久久久久久久久久久久久 | 国内精品久久久久久久久久久久 | 欧美黑人伦理 | 免费国产一区 | 国产成人aⅴ | v11av在线视频成人 | 亚洲男人天堂 | av免费不卡国产观看 | 91久久一区 | 日本在线视频二区 | 国产精品久久久久久婷婷天堂 | 欧美性生活久久久 | 国产亚洲精品久久久久久久软件 | 色综合欧美 | 精品久久久久久久久久久aⅴ | 在线观看中文字幕av | 视频在线色 | 成码无人av片在线观看网站 | 49vv看片免费 | 日韩在线播放中文字幕 | 日本精品免费观看 | 高清国产在线 | 欧美毛片在线观看 | 欧美人与禽性xxxxx杂性 | 小视频免费在线观看 | 红杏亚洲影院一区二区三区 | 久久久久国产成人精品亚洲午夜 |