2016-11-09 45 views
3

我正在玩pickle庫,當我發現有時,不同的類實例在相同的內存位置。不同的類實例使用相同的內存位置

兩者的下面例子展示所述行爲:

class DemoClass: 
    def __init__(self): 
     self.name = 'demoName' 

#example 1 
for i in range(3): 
    print (DemoClass()) 

#example 2 
[print(DemoClass()) for i in range(3)] 

#Output for both example 1 and example 2 
#Note that the memory locations are identical in the output 
<__main__.DemoClass object at 0x00CEE610> 
<__main__.DemoClass object at 0x00CEE610> 
<__main__.DemoClass object at 0x00CEE610> 

這是相當驚人的,以我的,所以也許你可以解釋爲什麼發生這種情況

在節目作爲我希望它是如下的方式。

demo = [DemoClass() for i in range(3)] 
for i in demo: 
    print (i) 

#Output 
<__main__.DemoClass object at 0x01F7E630> 
<__main__.DemoClass object at 0x01F7ED30> 
<__main__.DemoClass object at 0x01F7E670> 

回答

2

你的問題涉及Python如何分配內存。 tldr; Python使用堆來存儲內存。當資源被釋放時,它會進入堆頂部。

詳細回答

Python必須分配內存來創建一個對象的實例。爲了提高內存效率,Python memory manager有一堆內存位置可用於爲對象的實例化提供或保留。使用你的一些例子,你可以看到這在實踐中是如何工作的。

實施例#1

>>> for i in range(3): 
...  print DemoClass() 
... 
<test.DemoClass instance at 0x288b248> 
<test.DemoClass instance at 0x288b248> 
<test.DemoClass instance at 0x288b248> 

for循環的第一次迭代中,蟒使用第一個可用地址在其當前堆,即<0x288b248>,爲print呼叫建立的DemoClass一個實例。一旦print命令完成,內存地址將被釋放並返回到堆頂部的。在循環的下一次迭代期間,python利用第一個可用內存地址,該地址又是地址<0x288b248>。等

實施例#2

>>> for j in [DemoClass() for i in range(3)]: 
...  print j 
... 
<test.DemoClass instance at 0x288bcf8> 
<test.DemoClass instance at 0x288b290> 
<test.DemoClass instance at 0x288b638> 

這裏蟒生成列表,它將然後遍歷。創建列表要求爲每個元素創建DemoClass的一個新實例。這將從堆中取出前三個地址。循環完成後,列表從內存中釋放,如果我們再次撥打電話到print(DemoClass)我們會發現,蟒蛇再次重用內存。

>>> print DemoClass() 
<test.DemoClass instance at 0x288bcf8> 

實施例3(我的交替存儲器分配的實施例)

>>> for i in xrange(4): 
...  Demo = DemoClass() 
...  print(Demo) 
... 
<test.DemoClass instance at 0x288bcf8> 
<test.DemoClass instance at 0x288b290> 
<test.DemoClass instance at 0x288bcf8> 
<test.DemoClass instance at 0x288b290> 

在這個例子中,每次Demo被實例化作爲DemoClass一個實例,存儲器的段被分配給Demo。然而,調用print(Demo)免費分配給Demo內存。在下一循環的開始,一個新的內存段分配給Demo然後Demo覆蓋,此時它的原始內存地址返回到堆的頂部。然後用於Demo的存儲器地址在兩個存儲器地址之間交替。

4

在你的第2個實施例中,一旦向print呼叫已經完成,該對象不再具有參考,因此可以重新使用的類型的對象被創建的下一次。

第二,所有的實例同時有引用,因此必須是不同的。

對此行爲我不會依賴:例如,該對象可能還有其他未引用的實例在說謊。

3

當一個對象不存在了,它的位置是可以重複使用立即。
由於Python對象是引用計數的,只要沒有引用它們,它們就會消失。

如果事情的來龍去脈,你所期望的方式,你可以相當迅速地耗盡內存。

相關問題