यह एक बहुत लंबी व्याख्या है जो मैंने अपने एक सहकर्मी के लिए टाइप की थी। मुझे लगता है कि यह यहां भी मददगार होगा। हालांकि, धैर्य रखें। मैं असली मुद्दे पर आता हूं कि आप अंत की ओर हैं। एक टीज़र के रूप में, यह आपकी Line2D
वस्तुओं के चारों ओर अतिरिक्त संदर्भ होने का एक मुद्दा है ।
चेतावनी: इससे पहले कि हम गोता लगाते हैं एक अन्य नोट। यदि आप इसे बाहर परीक्षण करने के लिए आईपीथॉन का उपयोग कर रहे हैं, तो आईपीथॉन अपने स्वयं के संदर्भ रखता है और उनमें से सभी कमजोर नहीं हैं। तो, 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
समान 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>
तो, कहानी का नैतिक है, अपने आप को साफ करना। यदि आप उम्मीद करते हैं कि कुछ कचरा एकत्र किया जाएगा, लेकिन ऐसा नहीं है, तो आप कहीं बाहर एक संदर्भ छोड़ रहे हैं।