2014-12-13 42 views
9
>>> a=1 
>>> b=1 
>>> id(a) 
140472563599848 
>>> id(b) 
140472563599848 
>>> x=() 
>>> y=() 
>>> id(x) 
4298207312 
>>> id(y) 
4298207312 
>>> x1=(1) 
>>> x2=(1) 
>>> id(x1) 
140472563599848 
>>> id(x2) 
140472563599848 

直到這一點,我想這裏只會有一個不可變對象的副本,並且會被所有變量共享(指向)。python元組的內部

但是當我嘗試時,下面的步驟我明白我錯了。

>>> x1=(1,5) 
>>> y1=(1,5) 
>>> id(x1) 
4299267248 
>>> id(y1) 
4299267320 

任何人都可以請解釋我的內部?

回答

9
>>> x1=(1) 
>>> x2=(1) 

實際上是相同的

>>> x1=1 
>>> x2=1 

在Python,smaller numbers are internally cached。所以他們不會在內存中多次創建。這就是爲什麼的x1x2在此之前是相同的。

的一個元素的元組應在年底有一個逗號,這樣

>>> x1=(1,) 
>>> x2=(1,) 

當你做到這一點,也有與中只有一個元素來構建兩個新的元組。即使元組內的元素是相同的,但它們都是不同的元組。這就是爲什麼他們都有不同的id s。

讓我們看看你的最後一個例子並反彙編代碼。

compiled_code = compile("x1 = (1, 5); y1 = (1, 5)", "string", "exec") 

現在,

import dis 
dis.dis(compiled_code) 

會產生這樣的

1   0 LOAD_CONST    3 ((1, 5)) 
       3 STORE_NAME    0 (x1) 
       6 LOAD_CONST    4 ((1, 5)) 
       9 STORE_NAME    1 (y1) 
      12 LOAD_CONST    2 (None) 
      15 RETURN_VALUE 

它加載了一個恆定的值,該指數3,這是(1, 5),然後將其存儲在x1稱。同樣的,它會載入另一個常量值,索引號爲4,並將其存儲在y1中。如果我們看一下在代碼中的對象常量的列表,

print(compiled_code.co_consts) 

會給

(1, 5, None, (1, 5), (1, 5)) 

元素在位置34是我們在實際的代碼創建的元組。所以,Python不會爲每個不可變對象創建一個實例,總是。它的實現細節無論如何我們不必太擔心。

注:如果你想只有一個不可變對象的實例,你可以手動做這樣的

x1 = (1, 5) 
x2 = x1 

現在,無論是x2x1將參考同一個元組對象。

+1

而有*一個副本*的方法是:'x2 = x1' ... – 2014-12-13 14:19:30

+1

@JonClements包括現在的答案:-) – thefourtheye 2014-12-13 14:29:21