Value的比較符號用雙等號“==”,上例中比較l1和l2的Value要寫成“l1 == l2”,明顯兩者的Value是相等的。按照約定俗成的習慣,我們把Value值相等的兩個物件稱為“相等”,而把Id值相等的兩個物件稱為“相同”。
所以,準確地說,上例的l1與l2相等,但是他們不相同,l1==l2,但l1 is not l2。
特權種族:共用記憶體的物件
每個物件被建立出來的時候,就會確定其Id標識,也就是給它分配記憶體地址。通常來說,新物件的記憶體地址也是新的,會從未分配的可用地址中取。
但是,為了提高記憶體利用效率,對於一些常用的物件,如一些數值較小的數字物件、布林值物件、None物件、較短的字串物件等等,python採取共用物件記憶體的分配策略。
# 新分配記憶體地址的例子
ww=[1,2]
ee=[1,2]
id(ww)==id(ee) >>>False
a=2018
b=2018
id(a)==id(b) >>>False
# 共用記憶體地址的例子
a=100
b=100
id(a)==id(b) >>>True
f1=True
f2=True
id(f1)==id(f2) >>>True
n1=None
n2=None
id(n1)==id(n2) >>>True
s="python_cat"
t="python_cat"
id(s)==id(t) >>>True
這就意味著,python中出現了“特權種族”,執行環境早早就為它們分配好了記憶體地址,一旦要建立新的物件時,先去特權種族中查詢,有Type和Value相等的物件,則新物件不分配新的記憶體空間,而是指向已有物件。
“特權種族”的存在,使得我們不需要頻繁建立這些物件,既能提高已分配記憶體的使用率,又減少了建立物件、分配新記憶體的損耗。
對於共用記憶體地址的數字物件的取值範圍,根據這篇文章《Python中神秘的-5到256》(連結見文末)對python原始碼的分析,文中有如下結論:
Python中,對於整數物件,如果其值處於[-5,256]的閉區間內,則值相同的物件是同一個物件。
對於共用記憶體地址的字串物件的取值範圍,學習了幾篇對python原始碼分析的文章後(連結見文末),貓貓總結出大致有以下結論:
Python中,字串使用Intern機制實現記憶體地址共用,長度不超過20,且僅包括下劃線、數字、字母的字串才會被intern;涉及字串拼接時,編譯期最佳化結果會與執行期計算結果不同。
# 編譯對字串拼接的影響
s1 = "hell"
s2 = "hello"
"hell" + "o" is s2 >>>True
s1 + "o" is s2 >>>False
# "hell" + "o"在編譯時變成了"hello",
# 而s1+"o"因為s1是一個變數,在執行時才拼接,所以沒有被intern