2015-02-03 12 views
5

पहली नज़र में, ऐसा लगता है कि पाइथन की __del__ विशेष विधि सी ++ में विनाशक के समान फायदे प्रदान करती है। लेकिन पाइथन दस्तावेज के अनुसार (https://docs.python.org/3.4/reference/datamodel.html), कोई गारंटी है कि आपकी ऑब्जेक्ट की __del__ विधि कभी भी कॉल हो जाती है!आरएआईआई: __del__ का क्या मतलब है?

यह गारंटी नहीं है कि __del__() विधियों को ऑब्जेक्ट्स के लिए बुलाया जाता है जो दुभाषिया से बाहर निकलने पर मौजूद हैं।

तो दूसरे शब्दों में, विधि बेकार है! यही है ना एक हुक फ़ंक्शन जो वास्तव में बुलाया जा सकता है या नहीं, वास्तव में बहुत अच्छा नहीं करता है, इसलिए __del__ RAII के संबंध में कुछ भी नहीं प्रदान करता है। अगर मेरे पास कुछ आवश्यक सफाई है, तो मुझे कुछ समय चलाने के लिए इसकी आवश्यकता नहीं है, ओह, जब कभी भी जीसी वास्तव में ऐसा लगता है, तो मुझे विश्वसनीय रूप से, निश्चित रूप से और 100% समय चलाने की आवश्यकता है।

मुझे पता है कि अजगर संदर्भ प्रबंधकों, जो दूर उस कार्य के लिए अधिक उपयोगी हैं प्रदान करता है, लेकिन क्यों __del__ पर चारों ओर रखा गया था? क्या बात है?

+0

मुझे वास्तव में यह नहीं मिलता कि आप वास्तव में क्या पूछ रहे हैं। क्या आपका प्रश्न "क्या' __del__' अनिवार्य रूप से बेकार है? "? (मेरा मानना ​​है कि यह आपका प्रश्न है) इस मामले में मेरा मानना ​​है कि आप सी ++ या आरएआईआई के सभी संदर्भों को हटाकर प्रश्न को स्पष्ट करेंगे, जो पूरी तरह से असंबंधित हैं। यदि आपका प्रश्न है "पायथन में आरएआईआई को कैसे कार्यान्वित करें? क्या मैं इसके लिए' __del__' का उपयोग कर सकता हूं? " तो आपको शायद अपने प्रश्न में बहुत सारी चीजें बदलनी होंगी। – Bakuriu

+0

@ बाकुरीयू इस मामले का क्रूक्स है,'__del__ 'का बिंदु क्या है? क्या कोई विधि के लिए यथार्थवादी उपयोग केस नाम दे सकता है? – antred

उत्तर

1

क्योंकि __del__ कॉल किया जाता है। यह सिर्फ इतना है कि यह स्पष्ट नहीं होगा, क्योंकि यदि आपके पास सर्कुलर संदर्भ हैं, तो सीपीथॉन में, रीफ्रैंट तंत्र ऑब्जेक्ट रिक्लेमेशन (और इस प्रकार इसे __del__ के माध्यम से अंतिम रूप देने) का ख्याल नहीं रख सकता है और इसे कचरा कलेक्टर को सौंपना चाहिए।

कचरा कलेक्टर को तब एक समस्या है: वह परिपत्र संदर्भों को तोड़ने के लिए किस क्रम में नहीं जानता है, क्योंकि इससे अतिरिक्त समस्याएं उत्पन्न हो सकती हैं (उदाहरण के लिए उस स्मृति को मुक्त करता है जिसे किसी अन्य वस्तु के अंतिम रूप में आवश्यक करने के लिए आवश्यक है एकत्रित पाश का, एक segfault ट्रिगर)।

जिस बिंदु पर आप तनाव डालते हैं क्योंकि दुभाषिया उन कारणों से बाहर निकल सकता है जो इसे क्लीनअप करने के लिए रोकते हैं (उदा। यह segfaults, या कुछ सी मॉड्यूल अस्थायी रूप से बाहर निकलें())।

सुरक्षित ऑब्जेक्ट अंतिमकरण के लिए पीईपी 442 है जिसे 3.4 में अंतिम रूप दिया गया है। मेरा सुझाव है कि आप इसे देखें।

https://www.python.org/dev/peps/pep-0442/

+0

जो फिर से यह स्पष्ट करता है कि कैसे बेकार '__del__' है। उदाहरण के लिए, यदि मैं म्यूटेक्स गार्ड क्लास की ऑब्जेक्ट्स का उपयोग कहां से कर सकता हूं, तो मैं गार्ड क्लास की '__del__' विधि में अनलॉक नहीं कर सका, क्योंकि यह जानना पर्याप्त नहीं है कि जीसी जैसा लगता है कि' __del__' को कॉल किया जाएगा अपनी नौकरी कर रहा हूं ... मुझे म्यूटेक्स को ठीक से रिलीज़ करने की ज़रूरत है जब गार्ड ऑब्जेक्ट "गुंजाइश से बाहर हो जाता है" (मुझे पता है कि इसे खींच रहा है, पाइथन के स्कोपिंग नियम दिए गए हैं)। आईएमओ '__del__' प्रोग्रामर को झूठी छाप देता है कि पाइथन में आरएआईआई वास्तव में नहीं होने पर विनाशकों के माध्यम से करने योग्य है। इसके लिए आपको संदर्भ प्रबंधकों का उपयोग करना होगा। – antred

+1

यह बेकार नहीं है। आप अजगर में सी ++ कोड करने की कोशिश कर रहे हैं। मुद्दा यह है कि '__del__' एक विनाशक नहीं है। यह एक तंत्र है जो जगह पर है और बहुत सीमित मामलों में उपयोगी हो सकता है, लेकिन आप जावा फाइनलाइज़र की तरह, इस पर भरोसा नहीं कर सकते हैं। इस धागे को इसी तरह के प्रश्न के लिए देखें http://stackoverflow.com/questions/158174/why-would-you-ever-implement- –

9

__del__ एक finalizer है। यह एक विनाशक नहीं है। फाइनल और विनाशक पूरी तरह से अलग जानवर हैं।

विनाशकों को भरोसेमंद कहा जाता है, और केवल निर्धारिती स्मृति प्रबंधन (जैसे सी ++) वाले भाषाओं में मौजूद हैं। पायथन के संदर्भ प्रबंधक (with कथन) कुछ परिस्थितियों में समान प्रभाव प्राप्त कर सकते हैं। ये भरोसेमंद हैं क्योंकि किसी वस्तु का जीवन निश्चित रूप से तय किया जाता है; सी ++ में, वस्तुएं मर जाती हैं जब वे स्पष्ट रूप से delete डी या जब कुछ गुंजाइश निकलती है (या जब एक स्मार्ट सूचक अपने विनाश के जवाब में उन्हें हटा देता है)। और वह तब होता है जब विनाशक दौड़ते हैं।

अंतिमकर्ता विश्वसनीय रूप से नहीं कहा जाता है। फाइनलाइज़र का एकमात्र वैध उपयोग an emergency safety net (एनबी: यह आलेख एक .NET परिप्रेक्ष्य से लिखा गया है, लेकिन अवधारणाएं उचित रूप से अच्छी तरह से अनुवाद करती हैं)। उदाहरण के लिए, open() द्वारा लौटाई गई फ़ाइल ऑब्जेक्ट्स स्वचालित रूप से अंतिम रूप से बंद हो जाती हैं। लेकिन आप अभी भी उन्हें बंद करना चाहते हैं (उदाहरण के लिए with कथन का उपयोग करना)। ऐसा इसलिए है क्योंकि वस्तुओं को कचरा कलेक्टर द्वारा गतिशील रूप से नष्ट कर दिया जाता है, जो तुरंत चला सकता है या नहीं, और पीढ़ी के कचरे के संग्रह के साथ, यह किसी दिए गए पास में कुछ वस्तुओं को इकट्ठा या नहीं कर सकता है।चूंकि कोई भी नहीं जानता कि भविष्य में हम किस तरह के अनुकूलन का आविष्कार कर सकते हैं, यह मानना ​​सबसे सुरक्षित है कि आप यह नहीं जान सकते कि कचरा कलेक्टर आपकी वस्तुओं को इकट्ठा करने के लिए कब मिल जाएगा। इसका मतलब है कि आप अंतिम रूपकों पर भरोसा नहीं कर सकते हैं।

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

+1

फ़ाइनलाइज करें पृष्ठ पर उद्धरणों में से एक है > एक सही ढंग से लिखित प्रोग्राम यह नहीं मान सकता कि फाइनलर कभी भी दौड़ेंगे। यह सिर्फ मेरी धारणा को मजबूत करता है कि वे अनिवार्य रूप से बेकार हैं। यहां तक ​​कि आपकी टिप्पणी भी है कि प्रोग्रामर भूल गए सामानों को आजमाने और साफ करने के लिए उन्हें आपातकालीन सुरक्षा नेट के रूप में उपयोग किया जा सकता है क्योंकि वास्तव में यह ऐसा नहीं हो सकता है या नहीं हो सकता है। किसी भी दर पर, मुझे लगता है कि यह एक भयानक विचार है। यह सिर्फ सुरक्षा की झूठी भावना पैदा करता है, भ्रम पैदा करता है और मैला संसाधन प्रबंधन को प्रोत्साहित करता है (हे, मुझे साफ करने की ज़रूरत नहीं है, पायथन __might__ बस मेरे लिए यह करें)। – antred

+1

मैं आपसे सहमत हूं। यही कारण है कि मैं कभी भी अंतिमकरण का उपयोग नहीं करता। ओटीओएच, कमजोर संदर्भों से जुड़े फाइनलर्स कभी-कभी उपयोगी हो सकते हैं, उदाहरण के लिए आपको लाइव ऑब्जेक्ट्स का संग्रह बनाए रखने की आवश्यकता है लेकिन उन्हें जीवित रखना नहीं चाहते हैं। अधिक जानकारी के लिए 'कमजोर' देखें। – Kevin

+0

पीपीपी गारंटी देता है कि आपके __del__ को कॉल किया जाएगा। Cpython में यदि यह चक्र का हिस्सा है, तो इसे एटी ऑल नहीं कहा जाएगा। – fijal

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