小一點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里的數組一樣,每次創建都會分配內存空間。