これは私が私の同僚のためにタイプした非常に長い説明です。ここでも参考になると思います。ただし、しばらくお待ちください。私はあなたが終わりに向かって抱えている本当の問題に到達します。ティーザーと同じように、Line2D
オブジェクトへの追加の参照がぶら下がっているという問題です。
警告:詳しく説明する前にもう1つ注意してください。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()
上記で行ったことを使用して呼び出すと、軸のセットと1本の線を含む図が表示されます。
今、私たちは内容を見ましたながらlines
とax.lines
同じで、参照するオブジェクトことに注意することが非常に重要であるlines
変数がでreverencedオブジェクトと同じではありませんax.lines
、以下で見ることができるように。
>>> id(lines), id(ax.lines)
(212754584, 211335288)
結果として、から要素を削除lines
しても現在のプロットには何も影響しませんが、から要素をax.lines
削除すると、現在のプロットからその線が削除されます。そう:
>>>
>>> lines.pop(0)
>>>
>>> ax.lines.pop(0)
したがって、コードの2行目を実行すると、現在のプロットに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>
だから、話の教訓は、自分の後で片付けることです。何かがガベージコレクションされることを期待しているのにそうではない場合は、参照がどこかにぶら下がっている可能性があります。