python之tips(三)--為什么Python有相同的不可變對象id不同?


測試環境Python 2.7.3 & python 3.6

小一點int類型相等
s = 1
r = 1    # id(s) == id(r)    true
大一點的int類型就不一樣了?
s = 1111111111
r = 11111111111  # id(s) != id(r)
所有測試的float類型都不相等
s = 1.1
r  = 1.1
#id(s) != id(r)
所有測試的tuple類型都不相等
s = (1, 2)
r = (1, 2)
#id(s) != id(r)
所有測試的str都相等
s = 'aaaa'
r = 'aaaa'
#id(s) == id(r)

不是應該都復用相同的不可變對象用以節約內存嗎?

回答:

<Python源碼剖析>上解釋的很清楚:
Python里一切都是對象.所以1,2,3,4...這些整數也都是對象.這些基本的不可變對象在python里會被頻繁的引用,創建,如果不找到好的辦法的話很容易讓python引發效率瓶頸,所以python引入了整數對象池的機制.
intobject.c中代碼片段

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif
作者:知乎用戶
鏈接:https://www.zhihu.com/question/25050656/answer/34717037
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
  • int清楚寫了[-5, 256] 這些小整數被定義在了這個對象池里.所以當引用小整數時會自動引用整數對象池里的對象的.
  • string對象也是不可變對象,python有個intern機制,簡單說就是維護一個字典,這個字典維護已經創建字符串(key)和它的字符串對象的地址(value),每次創建字符串對象都會和這個字典比較,沒有就創建,重復了就用指針進行引用就可以了.

string實現了intern共享?我覺得是一種空間效率和時間效率的妥協。相比于數字,string本身參與的運算要少很多,而且string本身占據的空間也大許多,因此string的主要問題在于不共享帶來的空間浪費,所以string實現了很費時間的intern操作。對于數字情況正好相反。作為一個數字,需要做的運算要比string多太多了,而且大小比string也小很多。如果在計算10000+20000之前先花好久查找重復對象,導致一個1ms完成的加法花了100ms,我肯定想砸電腦的。

  • float類型可以認為每個賦值都是創建一個對象,因為float有點多,所以沒必要和int一樣了.
  • tuple它是不可變對象,理應和int和string一樣會做一個緩存,但是書上沒有說明,于是看了看源碼,發現tuple的數據結構很簡單,簡單到不能再簡單,就是一個數組,里面是元組的迭代對象,這個對象指向的是各個元素.最關鍵的是元組沒有實現intern機制!所以元組雖然是不可變對象,但它同時也是一個數組,這個數組和c里的數組一樣,每次創建都會分配內存空間。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • http://python.jobbole.com/85231/ 關于專業技能寫完項目接著寫寫一名3年工作經驗的J...
    燕京博士閱讀 7,628評論 1 118
  • 我們在學習理解一個事物時,往往遵循著由表及里的規律。第一步,我們學習一個事物的特性表現(feature)。在對事物...
    light_cong閱讀 7,811評論 1 14
  • 個人筆記,方便自己查閱使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik閱讀 67,768評論 0 5
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 1、透氣與保水的平衡 一直以來,國內多肉栽培在日系風格的嚴重影響下,都認為只有顆粒無塵土質才是最佳的種植材料。其實...
    夜之魔閱讀 1,242評論 0 1