Це дуже довге пояснення, яке я набрав для свого колеги. Думаю, це було б корисно і тут. Однак будьте терплячі. Я переходжу до реального питання, яке виникає у вас до кінця. Так само, як тизер, це питання наявності додаткових посилань на ваші Line2Dпредмети, що висяться.
ПОПЕРЕДЖЕННЯ: Ще одна примітка перед тим, як ми зануримося. Якщо ви використовуєте IPython для перевірки цього, IPython зберігає власні посилання, і не всі вони є слабкими посиланнями. Отже, тестування збору сміття в IPython не працює. Це просто плутає справи.
Гаразд, ось ми йдемо. Кожен matplotlibоб'єкт ( Figure, Axesтощо) забезпечує доступ до своїх дочірніх виконавців за допомогою різних атрибутів. Наступний приклад стає досить довгим, але повинен бути яскравим.
Спочатку ми створюємо Figureоб’єкт, а потім додаємо Axesоб’єкт до цієї фігури. Зверніть увагу, що axі fig.axes[0]є однаковим об'єктом (однаковим id()).
>>>
>>> fig = plt.figure()
>>> fig.axes
[]
>>>
>>> ax = fig.add_subplot(1,1,1)
>>>
>>>
>>> print ax
Axes(0.125,0.1;0.775x0.8)
>>> print fig.axes[0]
Axes(0.125,0.1;0.775x0.8)
>>> id(ax), id(fig.axes[0])
(212603664, 212603664)
Це також поширюється на лінії в об'єкті осей:
>>>
>>> lines = ax.plot(np.arange(1000))
>>>
>>> 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)
>>>
>>> id(lines[0]), id(ax.lines[0])
(216550352, 216550352)
Якби ви зателефонували, plt.show()використовуючи те, що було зроблено вище, ви побачите фігуру, що містить набір осей і один рядок:

Тепер, хоча ми переконались, що вміст linesі ax.linesє однаковим, дуже важливо відзначити, що об’єкт, на який посилається linesзмінна, не є таким, як об’єкт, на який поважають, ax.linesяк це можна побачити з наступного:
>>> id(lines), id(ax.lines)
(212754584, 211335288)
Як наслідок, видалення елемента з linesнічого не робить для поточної ділянки, але видалення елемента з ax.linesвидаляє цю лінію з поточної ділянки. Тому:
>>>
>>> lines.pop(0)
>>>
>>> ax.lines.pop(0)
Отже, якщо вам потрібно було запустити другий рядок коду, ви вилучили б Line2Dоб’єкт, що міститься в ньому, ax.lines[0]з поточного сюжету, і його не було б. Зверніть увагу, що це також можна зробити через ax.lines.remove()те, що ви можете зберегти Line2Dекземпляр у змінній, а потім передати його, ax.lines.remove()щоб видалити цей рядок, наприклад:
>>>
>>> lines.append(ax.plot(np.arange(1000)/2.0))
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84bd0>, <matplotlib.lines.Line2D object at 0xce84dx3>]

>>>
>>> ax.lines.remove(lines[0])
>>> ax.lines
[<matplotlib.lines.Line2D object at 0xce84dx3>]

Все вищезазначене працює fig.axesтак само добре, як і дляax.lines
Тепер справжня проблема тут. Якщо ми зберігаємо посилання , що міститься в ax.lines[0]в weakref.refоб'єкт, а потім спробувати видалити його, ми помітимо , що він не отримує сміття:
>>>
>>> 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>
>>>
>>> ax.lines.remove(wr())
>>> ax.lines
[]
>>>
>>> print wr
<weakref at 0xb758af8; to 'Line2D' at 0xb757fd0>
>>> print wr()
<matplotlib.lines.Line2D at 0xb757fd0>
Довідка ще живе! Чому? Це пов’язано з тим, що існує ще одне посилання на Line2Dоб’єкт, на яке вказує посилання wr. Пам’ятаєте, як linesне було того самого ідентифікатора, що ax.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.
>>>
>>> lines = []
>>> print lines
[]
>>> print wr
<weakref at 0xb758af8; dead>
Отже, мораль історії - прибирайте за собою. Якщо ви очікуєте, що щось буде зібраним сміттям, але це не так, ви, ймовірно, десь залишаєте посилання, що висить.