python中tuple屬於不可變類型,為何賦予相同值的tuple地址卻不同?
例如,t=(Ass,We,Can),tuple=(Ass,We,Can),而id(t)卻不等於id(tuple)。其他不可變類型比如a=1,b=1,則id(a)與id(b)相同。tuple的這個特性卻像極了list,例如l=[Ass,We,Can],list=[Ass,We,Can],則id(l)不等於id(list)。初學者,請各位前輩指點迷津
先思考這個問題:「值不可變」與「同樣值的必須是同一個對象」這兩者有必然關係么?
兩個對象一模一樣,用起來也一模一樣,又有什麼問題呢?只要你不去用它的id,id和is這種直接和對象地址相關的,可看作是一種「輔助語法功能」
這裡涉及到幾個問題,這是 id 的文檔
Return the 「identity」 of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same
id()
value.
可以看到 Python 對每個一個對象都提供一個唯一的 id 值。
&>&>&> id(1) == id(1)
True
&>&>&> id(1000) == id(1000)
True
&>&>&> id(10000) == id(10000)
True
這裡是因為 Python 在一個語句中對同樣的數值都解釋為了同一個對象。
2.
&>&>&> a = 1
&>&>&> b = 1
&>&>&> id(a) == id(b)
True
&>&>&> a = 257
&>&>&> b = 257
&>&>&> id(a) == id(b)
False
&>&>&> a = -5
&>&>&> b = -5
&>&>&> id(a) == id(b)
True
&>&>&> a = -6
&>&>&> b = -6
&>&>&> id(a) == id(b)
False
這是因為 Python 對整型 -5 ~ 256 都提前構造好了對象,後續所有值在這個範圍內的整型都是指向唯一的對象。目的是為了防止經常使用的數字不斷的被創建和銷毀。
3.
&>&>&> id(1000)
11300896
&>&>&> id(1001)
11300896
&>&>&> id(1002)
11300896
&>&>&> id(1003)
11300896
這是因為 Python 臨時對象不斷的被創建銷毀,所以不同的對象在復用同一個地址。python 只需要保證存活的對象的唯一 id 即可。
對於每個存活的 Tuple,id 不一樣是一件符合邏輯的事,儘管它們的內容一樣,但是它們是不同的對象。也沒有像小整型那樣的優化存在。
我先總結一下問題下兩位答主的內容。
- 值和id沒有必然聯繫,id只是一個對象唯一的標識符。可以看到,l的值變了,但對其id並無影響。&>&>&> l = [1, 2, 3]
&>&>&> id(l)
108841000&>&>&> l.append(4)&>&>&> l[1, 2, 3, 4]&>&>&> id(l)108841000 - 對於常用整數和常用字元串,Python都採用了一種駐留(interning)機制。對於整數,這個範圍是-5 ~ 256。對於字元串,則是僅包含"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"的字元串。所有在上述範圍內的值,都指向唯一的對象。
然後我想補充一點關於元組的不可變性。
元組是不可散列的,它的成員可以是可變對象,如列表、字典等。這也導致了元組的不可變其實是相對的。
&>&>&> t = (1, 2, 3, [4, 5])&>&>&> t[3].append(6)&>&>&> t(1, 2, 3, [4, 5, 6])如果想要絕對不可變的元組,請用frozenset。
這兩者有關係嗎。就好像你給兩個參量都賦值a為1,這倆的內存地址就一樣了么。
補充一點點
等號可以創建對象並指向,也可以指向現有的對象。和不可mutable沒有必然聯繫
推薦閱讀:
※如何優雅而高效地使用Matplotlib實現數據可視化
※通俗 Python 設計模式——外觀模式
※metaparse - 一個非常易用的Parser
※Python練習第一題,在圖片上加入數字