這是我輸入了我的一個同事很長的解釋。我認爲這也會有所幫助。不過,請耐心等待。我接觸到最後的真正問題。就像一個傳情,這是一個問題,有額外的參考你的Line2D
對象。
警告:另一個需要注意的地方是,如果你使用IPython來測試這個,IPython會保留它自己的引用,而不是所有的都是weakrefs。因此,在IPython中測試垃圾收集不起作用。它只是混淆了事情。
好的,我們走吧。每個matplotlib
對象(Figure
,Axes
等)通過各種屬性提供對其子藝術家的訪問。下面的例子變得相當長,但應該照亮。
我們首先創建一個Figure
對象,然後將一個Axes
對象添加到該圖中。請注意,ax
和fig.axes[0]
是相同的對象(相同id()
)。
>>> #Create a figure
>>> fig = plt.figure()
>>> fig.axes
[]
>>> #Add an axes object
>>> ax = fig.add_subplot(1,1,1)
>>> #The object in ax is the same as the object in fig.axes[0], which is
>>> # a list of axes objects attached to fig
>>> print ax
Axes(0.125,0.1;0.775x0.8)
>>> print fig.axes[0]
Axes(0.125,0.1;0.775x0.8) #Same as "print ax"
>>> id(ax), id(fig.axes[0])
(212603664, 212603664) #Same ids => same objects
這也延伸到在軸線對象:
>>> #Add a line to ax
>>> lines = ax.plot(np.arange(1000))
>>> #Lines and ax.lines contain the same line2D instances
>>> print lines
[<matplotlib.lines.Line2D object at 0xce84bd0>]
>>> print ax.lines
[<matplotlib.lines.Line2D object at 0xce84bd0>]
>>> print lines[0]
Line2D(_line0)
>>> print ax.lines[0]
Line2D(_line0)
>>> #Same ID => same object
>>> id(lines[0]), id(ax.lines[0])
(216550352, 216550352)
如果你使用的是什麼上面做打電話plt.show()
,你會看到一個包含組軸和一個線圖:
現在,雖然我們已經看到的lines
和ax.lines
內容是
>>> id(lines), id(ax.lines)
(212754584, 211335288)
作爲結果,從移除元素:同樣,必須指出,由lines
變量引用的對象是不一樣的由ax.lines
尊崇的對象作爲可以由以下可以看出是很重要lines
對當前繪圖沒有任何影響,但從ax.lines
中刪除元素會從當前繪圖中刪除該線條。所以:
>>> #THIS DOES NOTHING:
>>> lines.pop(0)
>>> #THIS REMOVES THE FIRST LINE:
>>> ax.lines.pop(0)
所以,如果你運行代碼的第二行,你會要從當前情節ax.lines[0]
包含Line2D
對象,它會消失。請注意,這也可以通過ax.lines.remove()
意義來做到這一點,你可以在一個變量保存Line2D
實例,然後將它傳遞給ax.lines.remove()
刪除線,就像這樣:
>>> #Create a new line
>>> lines.append(ax.plot(np.arange(1000)/2.0))
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84bd0>, <matplotlib.lines.Line2D object at 0xce84dx3>]
>>> #Remove that new line
>>> ax.lines.remove(lines[0])
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84dx3>]
以上所有作品都適用於fig.axes
以及它適用於ax.lines
現在,真正的問題在這裏。如果我們存儲包含在ax.lines[0]
爲weakref.ref
對象的引用,然後嘗試刪除它,我們會發現,收集它不會垃圾:
>>> #Create weak reference to Line2D object
>>> from weakref import ref
>>> wr = ref(ax.lines[0])
>>> print wr
<weakref at 0xb758af8; to 'Line2D' at 0xb757fd0>
>>> print wr()
<matplotlib.lines.Line2D at 0xb757fd0>
>>> #Delete the line from the axes
>>> ax.lines.remove(wr())
>>> ax.lines
[]
>>> #Test weakref again
>>> print wr
<weakref at 0xb758af8; to 'Line2D' at 0xb757fd0>
>>> print wr()
<matplotlib.lines.Line2D at 0xb757fd0>
基準仍然活着!爲什麼?這是因爲wr
中的參考指向Line2D
對象還有其他參考。請記住lines
與ax.lines
沒有相同的ID,但包含相同的元素?那是這個問題。
>>> #Print out lines
>>> print lines
[<matplotlib.lines.Line2D object at 0xce84bd0>, <matplotlib.lines.Line2D object at 0xce84dx3>]
To fix this problem, we simply need to delete `lines`, empty it, or let it go out of scope.
>>> #Reinitialize lines to empty list
>>> lines = []
>>> print lines
[]
>>> print wr
<weakref at 0xb758af8; dead>
因此,故事的寓意是,自己清理。如果你期望有東西被垃圾收集,但事實並非如此,那麼你可能會在某處留下一個參考。
我運行了你的代碼,得到了: [8:37 pm] @flattop:〜/ Desktop/sandbox> python delete_lines.py 我在ubuntu 10.04中使用matplotlib版本0.99.1.1 –
2011-02-13 02:31:28
@David Morton我剛降級到0.99.1,現在我重現了你的問題。我想我只能推薦升級到1.0.1。自0.99.x以來有很多錯誤修正。 – Paul 2011-02-13 03:31:03
謝謝!非常感謝你的幫助。 – 2011-02-13 05:07:56