Đây là một lời giải thích rất dài mà tôi gõ lên cho một đồng nghiệp của tôi. Tôi nghĩ nó cũng hữu ích ở đây. Hãy kiên nhẫn, mặc dù. Tôi nhận được vấn đề thực sự mà bạn đang có để kết thúc. Cũng giống như một lời trêu ghẹo, đó là vấn đề có thêm tham chiếu đến các đối tượng Line2D
của bạn treo xung quanh.
CẢNH BÁO: Một lưu ý khác trước khi chúng tôi đi sâu vào. Nếu bạn đang sử dụng IPython để kiểm tra điều này, IPython giữ tham chiếu của riêng nó và không phải tất cả chúng đều yếu. Vì vậy, kiểm tra bộ sưu tập rác trong IPython không hoạt động. Nó chỉ gây nhầm lẫn vấn đề.
OK, ở đây chúng tôi đi. Mỗi đối tượng matplotlib
(Figure
, Axes
, v.v.) cung cấp quyền truy cập cho các nghệ sĩ trẻ thông qua các thuộc tính khác nhau. Ví dụ sau đây nhận được khá dài, nhưng nên được chiếu sáng.
Chúng tôi bắt đầu bằng cách tạo đối tượng Figure
, sau đó thêm đối tượng Axes
vào hình đó. Lưu ý rằng ax
và fig.axes[0]
là cùng một đối tượng (giống như 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
này cũng mở rộng đến dòng trong một trục đối tượng:
>>> #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)
Nếu bạn đã gọi plt.show()
sử dụng những gì đã được thực hiện ở trên, bạn sẽ thấy một con số có chứa một tập hợp các trục và một dòng duy nhất :
Bây giờ, trong khi chúng ta đã thấy rằng nội dung của lines
và ax.lines
là giống nhau, nó là rất quan trọng cần lưu ý rằng đối tượng được tham chiếu bởi biến lines
là không giống như các đối tượng tôn kính bởi ax.lines
như có thể thấy bằng cách như sau:
>>> id(lines), id(ax.lines)
(212754584, 211335288)
Như một hệ quả, loại bỏ một phần tử từ lines
không làm gì với cốt truyện hiện tại, nhưng việc xóa một phần tử khỏi ax.lines
sẽ xóa dòng đó khỏi ô hiện tại. Vì vậy:
>>> #THIS DOES NOTHING:
>>> lines.pop(0)
>>> #THIS REMOVES THE FIRST LINE:
>>> ax.lines.pop(0)
Vì vậy, nếu bạn đã chạy dòng thứ hai của mã này, bạn sẽ loại bỏ các đối tượng Line2D
chứa trong ax.lines[0]
từ cốt truyện hiện tại và nó sẽ được biến mất. Lưu ý rằng điều này cũng có thể được thực hiện thông qua ax.lines.remove()
ý nghĩa mà bạn có thể tiết kiệm một trường hợp Line2D
trong một biến, sau đó vượt qua nó để ax.lines.remove()
xóa dòng đó, như vậy:
>>> #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>]
Tất cả các công việc trên cho fig.axes
cũng như hoạt động đối với ax.lines
Bây giờ, vấn đề thực sự ở đây. Nếu chúng ta lưu trữ các tài liệu tham khảo chứa trong ax.lines[0]
vào một đối tượng weakref.ref
, sau đó cố gắng để xóa nó, chúng ta sẽ nhận thấy rằng nó không được thu gom rác thải:
>>> #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>
Tham chiếu vẫn còn sống! Tại sao? Điều này là do vẫn có một tham chiếu khác đến đối tượng Line2D
mà tham chiếu trong số wr
trỏ đến. Hãy nhớ cách lines
không có cùng một ID là ax.lines
nhưng chứa cùng một yếu tố? Vâng, đó là vấn đề.
>>> #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>
Vì vậy, tinh thần của câu chuyện là, dọn sạch sau khi chính bạn. Nếu bạn mong đợi một cái gì đó để được thu thập rác nhưng nó không phải là, bạn có khả năng để lại một tài liệu tham khảo treo ra một nơi nào đó.
Tôi đã chạy mã của bạn và nhận được: [8:37 pm] @flattop: ~/Desktop/sandbox> python delete_lines.py Tôi đang sử dụng phiên bản matplotlib 0.99.1.1 trong ubuntu 10.04 –
@David Morton Tôi vừa hạ cấp xuống 0.99.1 và bây giờ tôi đã tái tạo sự cố của bạn. Tôi đoán tôi chỉ có thể khuyên bạn nên nâng cấp lên 1.0.1.Đã có * nhiều * số sửa lỗi từ 0.99.x – Paul
Cảm ơn! Tối đánh giá rất cao sự giúp đỡ của bạn. –