2016-04-19 12 views
5

मेरे पास परिभाषित कक्षा में __del__ विधि है, जिसे सीटीएस इंटरफ़ेस में सी ++ नया कॉल करके बनाई गई कुछ सी ++ ऑब्जेक्ट्स को हटाने के लिए है। जब मैं अपनी कक्षा का एक उदाहरण नष्ट कर देता हूं तो मैं इन वस्तुओं को हटाना चाहता हूं। मैं कक्षा का एक टुकड़ा यहाँ दिखाया गया है:पायथन 3, सुपर .__ डेल __()

class Graph(QtCore.QObject): 
    def __init__(self): 
     super().__init__() 
     #list of objects created by calls to ctypes to create pointers to C++ objects which are instantiated with C++ new 
     self.graphs = [] 

    def __del__(self): 
     print("in delete method") 
     for graph in self.graphs: 
      # call the C++ delete to free the storage used by this graph 
      myctypes.graphDelete(graph) 
     super().__del__() 

जब मेरे ग्राफ़ वर्ग का एक उदाहरण हटा दी जाती है, __del__ विधि कहा जाता है और मैं अपने प्रिंट बयान देख सकते हैं और जब मैं नाशक विधि में एक ब्रेकपाइंट सेट सी ++ कोड, जैसा कि अपेक्षित है, यह ऑब्जेक्ट को हटा देता है।

super().__del__() 
AttributeError: 'super' object has no attribute '__del__' 

मैं कैसे सुनिश्चित करूँ कि माता पिता वर्ग (QtCore.QObject) अगर मैं बच्चा कक्षा में अपने ही __del__ विधि परिभाषित या होगा हटा दी जाती है: हालांकि, जब मेरी __del__ विधि super().__del__() कहता है, मैं त्रुटि संदेश मिलता है अभिभावक वर्ग स्वचालित रूप से हटा दिया जाएगा?

+0

कृपया 'सुपर (ग्राफ, स्वयं) .__ del __() 'और' QtCore.QObject .__ del __ (self)' आज़माएं। इससे कोई फर्क नहीं पड़ता है, लेकिन शायद यह काम करता है। – kay

+0

धन्यवाद Kay, मैंने बस उन दोनों की कोशिश की और मुझे अभी भी विशेषता त्रुटि मिल गई है। – inwhack

+0

@inwhack, मेरा मानना ​​है कि कचरा कलेक्टर अपना काम करेगा, अप्रयुक्त उदाहरणों/चरों को साफ करेगा –

उत्तर

4

आपके द्वारा प्राप्त की जाने वाली कक्षा में __del__() नहीं है। तो इसे कॉल करने का प्रयास करना एक त्रुटि है।

अब, यदि आप अपनी कक्षा को एकाधिक विरासत परिदृश्य में उपयोग करने की उम्मीद करते हैं, तो विधि समाधान आदेश (एमआरओ) में अगली कक्षा वास्तव में आपकी कक्षा के माता-पिता नहीं हो सकती है। और वह कक्षा, जो भी हो, __del__() विधि हो सकती है। इसलिए, यदि आप उस मामले के बारे में चिंतित हैं, तो आप try का उपयोग कर सकते हैं और AttributeError निगल सकते हैं, या hasattr() का उपयोग कर सकते हैं, या getattr() का उपयोग एक डमी लैम्ब्डा के साथ डिफ़ॉल्ट मान के रूप में करते हैं।

यहाँ प्रत्येक का एक उदाहरण है:

# there is a minor bug here, can you guess what it is? 
try: 
    super().__del__(self) 
except AttributeError: 
    pass 

# better version of the above 
s = super() 
try: 
    s.__del__ 
except AttributeError: 
    pass 
else: 
    s.__del__(self) 

s = super() 
if hasattr(s, "__del__"): 
    s.__del__(self) 

getattr(super(), "__del__", lambda self: None)(self) 
+1

"मामूली बग" जिसमें मैं कोड टिप्पणी में संदर्भित करता हूं वह यह है कि हम केवल * एट्रिब्यूट एरर 'को पकड़ नहीं रहे हैं आपके सुपरक्लास पर विशेषता लुकअप। दूसरे शब्दों में, यदि एमआरओ में अगली कक्षा में '__del__' मौजूद है, लेकिन इसे कॉल करना 'एट्रिब्यूट एरर' बढ़ाता है, तो यह त्रुटि रिपोर्ट होने की बजाय गलत तरीके से निगल जाएगी। लेकिन 60% समय, यह हर बार काम करता है। – kindall

1

__del__ की भूमिका वस्तु को हटाने के लिए नहीं है: यह से पहले वस्तु स्वचालित रूप से हटा दिया जाता है कहा जाता है। इसलिए यह ठीक है अगर आपका मूल वर्ग __del__ परिभाषित नहीं करता है। अगर यह आपको परेशान कर रहा है तो super().__del__() पर कॉल न करें।

रिकॉर्ड के लिए, ऑब्जेक्ट्स के पास डिफ़ॉल्ट __del__ क्यों नहीं है, यह संदर्भ है कि __del__ वाले ऑब्जेक्ट्स संदर्भ चक्रों (पायथन 3.4 तक) के मामले में कचरा नहीं एकत्र किए गए थे। अधिक जानकारी के लिए, gc.garbage in Python 3.3 और gc.garbage in Python 3.4 के लिए दस्तावेज़ पढ़ें।

+0

क्या आप दूसरे पैराग्राफ पर विस्तार कर सकते हैं? मुझे समझ में नहीं आता क्या इसका मतलब यह है कि यदि आपके पास 'def __del __ (स्वयं) है: 'आपकी कक्षा में वस्तु ऑब्जेक्ट कचरा नहीं होगी? धन्यवाद! (पीएस। ज्यादातर पाइथन 2.7) –

+0

के संबंध में यदि आपके पास संदर्भ चक्र है और चक्र में वस्तुओं में से एक में '__del__' है, तो ऑब्जेक्ट्स का निपटारा कभी नहीं किया जाता है। [Gc.garbage 3.3 में देखें] (https://docs.python.org/3.3/library/gc.html#gc.garbage) और [gc.garbage 3.4 में] (https://docs.python.org/ 3.4/पुस्तकालय/gc.html # gc.garbage) –