이것은 제 동료를 위해 입력 한 매우 긴 설명입니다. 여기에서도 도움이 될 것 같습니다. 하지만 인내심을 가지십시오. 나는 당신이 마지막에 직면하고있는 진짜 문제에 도달합니다. 티저와 마찬가지로 Line2D
주변에있는 개체에 대한 추가 참조가있는 문제입니다 .
경고 : 시작하기 전에 또 하나의 참고 사항이 있습니다. IPython을 사용하여 이것을 테스트하는 경우 IPython은 자체 참조를 유지하며 모든 참조가 weakref가 아닙니다. 따라서 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)
이것은 또한 axes 객체의 선으로 확장됩니다.
>>>
>>> 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
ID가 같지 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>
그래서 이야기의 교훈은 자신을 정리하는 것입니다. 가비지 수집을 기대하지만 그렇지 않은 경우 어딘가에 참조를 남겨 두는 것입니다.