2011-04-18 9 views
8

निम्न उदाहरण कोडकिसी ऑब्जेक्ट के दूसरे प्रारंभिकरण पर, __init__ को __del__ से पहले क्यों कहा जाता है?

class A: 
    def __init__(self, i): 
     self.i = i 
     print("Initializing object {}".format(self.i)) 

    def __del__(self): 
     print("Deleting object {}".format(self.i)) 

for i in [1, 2]: 
    a = A(i) 

वस्तु बनाना भीतर पाश आश्वस्त करने के लिए है कि इससे पहले कि नया एक वस्तु बनाया जा होगा एक की नाशक कहा जाएगा इरादा था पर विचार करें। लेकिन जाहिरा तौर पर निम्न होता है:

आरंभ किया जा रहा वस्तु 1

आरंभ किया जा रहा वस्तु 2

हटाया जा रहा वस्तु 1

हटाया जा रहा वस्तु 2

क्यों वस्तु 1 का नाशक है केवल नई वस्तु शुरू करने के बाद बुलाया गया है? क्या यह एक इरादा व्यवहार है? मुझे पता है कि लूप के लिए अजगर में कोई गुंजाइश नहीं है। उदाहरण के लिए, सी ++ में, 1 के विनाशक को निश्चित रूप से ऑब्जेक्ट 2 के लिए कन्स्ट्रक्टर के समक्ष कहा जाएगा (कम से कम यदि ऑब्जेक्ट लूप के भीतर घोषित किया गया हो)।

मेरे कार्यक्रम में मैं यह आश्वस्त करना चाहता हूं कि नया ऑब्जेक्ट बनाया गया है इससे पहले कि नया ऑब्जेक्ट बनाया गया हो। क्या लूप के अंत में a को हटाने से अलग कोई और संभावना है?

अग्रिम धन्यवाद।

+0

दिलचस्प बात तब होती है जब आप लूप को '[1,2,3]' से अधिक बदलते हैं। – kennytm

+1

यह एक अच्छा साक्षात्कार सवाल करेगा। – pajton

+4

अंतिम अनुच्छेद पुन: आप ऐसा नहीं करना चाहते हैं। क्योंकि आप नहीं कर सकते (जीसी गैर-निर्धारिती है और refcounting एक कार्यान्वयन विस्तार है), और आपको वैसे भी जरूरत नहीं है। यदि आपके पास निपटान करने के लिए संसाधन हैं, तो संदर्भ प्रबंधक ('कथन के साथ) का उपयोग करें या' .close() 'जैसी विधि जोड़ें और सुनिश्चित करें कि इसे कॉल किया गया है। – delnan

उत्तर

11

दूसरे वस्तु का निर्माण नाम रिबाउंड से पहले होता है और पहली वस्तु का निपटारा किया जाता है।

  1. पहला A तत्काल है।
  2. a बाध्य है।
  3. दूसरा A तत्काल है।
  4. a रिबाउंड है, और पहले A का निपटारा किया गया है।
  5. कार्यक्रम समाप्त होता है, और दूसरा A का निपटारा किया जाता है।
+0

त्वरित और विस्तृत उत्तर के लिए धन्यवाद! क्या मुझे सुनिश्चित करने के लिए 'del' का उपयोग करना चाहिए, तो पिछला उदाहरण तब हटा दिया गया है? –

+0

यह कार्यान्वयन विस्तार नहीं है? –

+0

आप सही हैं। मुझे इसे इस तरह से रखने दें: मुझे लगता है कि कक्षा ए की परिभाषा के भीतर इसे लागू करने का कोई तरीका नहीं है? –

9

आप आजीवन निर्भरताओं की योजना बनाते समय कचरा कलेक्टर के कार्यान्वयन विवरण पर भरोसा नहीं कर सकते हैं। आपको इसे स्पष्ट रूप से एक या दूसरे तरीके से करने की ज़रूरत है।

प्रसंग प्रबंधकों वसंत मन में, उदाहरण के लिए:

from contextlib import contextmanager 

@contextmanager 
def deleting(obj): 
    try: 
     yield 
    finally: 
     del(obj) 

class A: 
    def __init__(self, i): 
     self.i = i 
     print("Initializing object {}".format(self.i)) 

    def __del__(self): 
     print("Deleting object {}".format(self.i)) 

for i in [1,2]: 
    with deleting(A(i)) as obj: 
     pass 

print 

for i in [1,2]: 
    a = A(i) 

यह निम्न उत्पादन का उत्पादन:

Initializing object 1 
Deleting object 1 
Initializing object 2 
Deleting object 2 

Initializing object 1 
Initializing object 2 
Deleting object 1 
Deleting object 2 
+0

प्राप्त करने का प्रयास कर रहा है धन्यवाद विस्तृत उत्तर के लिए बहुत कुछ –

0

यह मानते हुए कि आप वस्तु चाहते हैं अपने अंतिम मूल्य के रूप में परिभाषित किया जा करने के लिए जब पाश बाहर निकलता है , अंत पाश के लिए की पर स्पष्ट रूप से वस्तु को नष्ट नहीं करते हैं, लूप के शुरुआत पर ऐसा करते हैं, इस तरह:

class A: 
    def __init__(self, i): 
     self.i = i 
     print("Initializing object {}".format(self.i)) 

    def __del__(self): 
     print("Deleting object {}".format(self.i)) 

for i in [1, 2, 3]: 
    a = None 
    a = A(i) 

कि प्रिंट:

Initializing object 1 
Deleting object 1 
Initializing object 2 
Deleting object 2 
Initializing object 3 
Deleting object 3 

(नोट: Ignatio कारण है कि यह जिस तरह से यह काम करता है काम करता है के बारे में सही है, लेकिन KennyTM भी सही है, यह है कि यह और अधिक स्पष्ट क्या हो रहा है आप बनाना चाहिए बनाने के लिए यह लूप के माध्यम से कम से कम तीन बार जाता है।)

संबंधित मुद्दे