2010-04-05 15 views
6

मैं सीपीथन कचरा कलेक्टर के आंतरिक को समझने की कोशिश कर रहा हूं, खासकर जब विनाशक कहलाता है। अब तक, व्यवहार सहज है, लेकिन निम्न मामला मुझे यात्रा करता है:जब सीपीथन कचरा कलेक्टर अक्षम किया जाता है तो विनाशक क्यों कहा जाता है?

  1. जीसी को अक्षम करें।
  2. कोई ऑब्जेक्ट बनाएं, फिर उसके संदर्भ को हटा दें।
  3. ऑब्जेक्ट नष्ट हो गया है और _____del_____ विधि कहा जाता है।

मैंने सोचा कि यह केवल तभी होगा जब कचरा कलेक्टर सक्षम किया गया हो। क्या कोई समझा सकता है कि ऐसा क्यों होता है? क्या विनाशक को बुलाए जाने का कोई तरीका है?

import gc 
import unittest 

_destroyed = False 

class MyClass(object): 

    def __del__(self): 
     global _destroyed 
     _destroyed = True 

class GarbageCollectionTest(unittest.TestCase): 

    def testExplicitGarbageCollection(self): 
     gc.disable() 
     ref = MyClass() 
     ref = None 
     # The next test fails. 
     # The object is automatically destroyed even with the collector turned off. 
     self.assertFalse(_destroyed) 
     gc.collect() 
     self.assertTrue(_destroyed) 

if __name__=='__main__': 
    unittest.main() 

अस्वीकरण: इस कोड उत्पादन के लिए नहीं कर रहा है - मैं पहले से ही देखा है कि यह बहुत ही कार्यान्वयन-विशिष्ट है और Jython पर काम नहीं करता।

उत्तर

9

अजगर दोनों संदर्भ कचरा संग्रहण और चक्रीय कचरा संग्रहण की गिनती है, और यह उत्तरार्द्ध है कि gc मॉड्यूल नियंत्रित करता है। संदर्भ गणना को अक्षम नहीं किया जा सकता है, और इसलिए तब भी होता है जब चक्रीय कचरा कलेक्टर बंद हो जाता है।

चूंकि ref = None के बाद आपके ऑब्जेक्ट में कोई संदर्भ नहीं छोड़ा गया है, इसकी __del__ विधि को इसकी संदर्भ गणना शून्य के परिणामस्वरूप कहा जाता है।

the documentation में एक सुराग है: "कलेक्टर पूरक संदर्भ गणना पहले ही पाइथन में उपयोग की जाती है ..." (मेरा जोर)।

आप इसे इस निर्माता देकर वस्तु ही देखें, ताकि उसके संदर्भ गिनती शून्य करने के लिए जाना नहीं है, उदाहरण के लिए बनाने के द्वारा फायरिंग से पहले दावे बंद कर सकते हैं:

def __init__(self): 
    self.myself = self 

लेकिन अगर आप ऐसा करो, दूसरा दावा आग लग जाएगा। ऐसा इसलिए है क्योंकि __del__ विधियों के साथ कचरा चक्र एकत्र नहीं किया जाता है - gc.garbage के लिए प्रलेखन देखें।

4

कचरा कलेक्टर की आपकी परिभाषा के आधार पर, सीपीथन में दो कचरा कलेक्टर हैं, संदर्भ एक गिनती है, और दूसरा।
संदर्भ काउंटर हमेशा काम कर रहा है, और इसे बंद नहीं किया जा सकता है, क्योंकि यह काफी तेज और हल्का है जो सिस्टम के रन टाइम को गंभीर रूप से प्रभावित नहीं करता है।
दूसरा (चिह्न और स्वीप का कुछ भिन्नता, मुझे लगता है), हर बार चला जाता है, और अक्षम किया जा सकता है। ऐसा इसलिए है क्योंकि इसे चलने के दौरान दुभाषिया को रोका जाना आवश्यक है, और यह गलत पल में हो सकता है, और बहुत सी CPU समय का उपभोग कर सकता है।
इसे अक्षम करने की यह क्षमता उन समय के लिए है जब आप कुछ ऐसा करने की उम्मीद करते हैं जो समय महत्वपूर्ण है, और इस जीसी की कमी से आपको कोई समस्या नहीं होगी।

+0

क्या यह "दो कचरा कलेक्टर" कार्यान्वयन कहीं भी दस्तावेज है? – Frederik

+0

एलेक्स मार्टेलि के उत्तर, और इसके संबंधित लिंक पर एक नज़र डालें। यह संभवतः किसी और चीज से बेहतर है जिसके साथ मैं आ सकता हूं। –

4

डॉक्स here बताएं कि किस तरह क्या "वैकल्पिक कचरा कलेक्टर" कहा जाता है वास्तव में चक्रीय कचरा (ऐसा दर्द जिसमें संदर्भ गिनती पकड़ नहीं होगा) के एक कलेक्टर है।संदर्भ गिनती here समझाया गया है, चक्रीय जीसी के साथ अपने परस्पर क्रिया के लिए एक इशारा के साथ:

अजगर पारंपरिक संदर्भ गिनती कार्यान्वयन का उपयोग करता है, यह भी एक चक्र डिटेक्टर कि संदर्भ चक्र पता लगाने के लिए काम करता है प्रदान करता है। यह अनुप्रयोगों को के बारे में चिंता करने की अनुमति देता है प्रत्यक्ष या अप्रत्यक्ष परिपत्र संदर्भ; कचरा संग्रह की कमजोरी केवल संदर्भ गणना का उपयोग करके लागू की गई है। संदर्भ चक्रों में ऑब्जेक्ट्स शामिल हैं जो में (संभवतः अप्रत्यक्ष) संदर्भ स्वयं हैं, ताकि में प्रत्येक ऑब्जेक्ट में संदर्भ संदर्भ हो जो गैर-शून्य है। विशिष्ट संदर्भ गिनती कार्यान्वयन भले ही चक्र खुद के लिए कोई आगे संदर्भ हैं, सक्षम स्मृति एक संदर्भ चक्र, या चक्र में वस्तुओं से संदर्भित में किसी भी वस्तुओं से संबंधित को पुनः प्राप्त करने के लिए नहीं कर रहे हैं।