दिलचस्प पोस्ट
Iostream और iostream.h के बीच का अंतर सी ++ कोड / प्रोजेक्ट में मेमोरी रिसाव कैसे ढूंढें? दोहरे y- अक्ष ggplot के साथ पहलुओं का उपयोग कैसे करें IBeacon ब्लूटूथ प्रोफाइल क्या है VS2010 वेब परिनियोजन पैकेज का उपयोग करते हुए आप अतिरिक्त फ़ाइलों को कैसे शामिल करते हैं? स्ट्रिंग में किसी वर्ण की सभी घटनाओं को कैसे बदलना है? Google App Engine में सभी डेटास्टोर को कैसे हटाएं? क्या Google प्रपत्र से डेटा का उपयोग करते हुए एक Google फ़ॉर्म 'प्रीफिल' करना संभव है? अतिरिक्त वैकल्पिक टेम्पलेट पैरामीटर के साथ मानक पुस्तकालय कंटेनर? नियमित अभिव्यक्ति के साथ सीरिलिक वर्णों का मिलान कैसे करें जावा 32-बिट बनाम 64-बिट संगतता एंड्रॉइड में मेमोरी एनालाइज़र टूल? एएसपी.नेट पृष्ठ जीवन चक्र विवरण एक जेएसओएन स्ट्रिंग लेते हुए, उसे एक नक्शा इंटरफ़ेस {}, संपादन, और इसे बाइट में मार्शल करने में असमर्थ बनाते हुए अधिक जटिल लगता है तो यह होना चाहिए त्रुटि LNK2038: '_MSC_VER' के लिए बेमेल पता चला: मान '1600' CppFile1.obj में मान '1700' से मेल नहीं खाती

क्यों __init __ () हमेशा __new __ () के बाद कहा जाता है?

मैं सिर्फ अपनी कक्षाओं में से एक को सुव्यवस्थित करने की कोशिश कर रहा हूं और फ़्लायवेट डिज़ाइन पैटर्न के रूप में उसी शैली में कुछ कार्यक्षमता पेश की है।

हालांकि, मैं थोड़ा उलझन में हूं कि __init__ हमेशा __new__ बाद क्यों कहा जाता है मुझे यह उम्मीद नहीं थी। क्या कोई मुझे बता सकता है कि ऐसा क्यों हो रहा है और मैं अन्यथा इस कार्यक्षमता को कैसे लागू कर सकता हूं? (कार्यान्वयन को __new__ में डालने के अलावा जो काफी __new__ लगता है।)

यहां एक उदाहरण है:

 class A(object): _dict = dict() def __new__(cls): if 'key' in A._dict: print "EXISTS" return A._dict['key'] else: print "NEW" return super(A, cls).__new__(cls) def __init__(self): print "INIT" A._dict['key'] = self print "" a1 = A() a2 = A() a3 = A() 

आउटपुट:

 NEW INIT EXISTS INIT EXISTS INIT 

क्यूं कर?

वेब के समाधान से एकत्रित समाधान "क्यों __init __ () हमेशा __new __ () के बाद कहा जाता है?"

__new__ का उपयोग करें जब आपको एक नया उदाहरण बनाने के लिए नियंत्रण की आवश्यकता हो। __init__ का उपयोग करें जब आपको एक नया उदाहरण के प्रारंभ को नियंत्रित करने की आवश्यकता हो।

__new__ उदाहरण के निर्माण का पहला चरण है। इसे पहले कहा जाता है, और आपकी कक्षा के एक नए उदाहरण को वापस करने के लिए जिम्मेदार है। इसके विपरीत, __init__ कुछ भी वापस नहीं करता; इसे बनाया गया है के बाद यह उदाहरण शुरू करने के लिए ही जिम्मेदार है।

सामान्यतया, आपको __new__ को ओवरराइड करने की आवश्यकता नहीं होगी जब तक कि आप एक अस्थायी प्रकार sub , str, int, unicode या tuple subclassing नहीं कर रहे हैं।

से: http://mail.python.org/pipermail/tutor/2008-April/061426.html

आपको यह विचार करना चाहिए कि आप जो भी करने की कोशिश कर रहे हैं वह आमतौर पर फैक्ट्री के साथ किया जाता है और ऐसा करने का सबसे अच्छा तरीका है __new__ का उपयोग करना एक अच्छा साफ समाधान नहीं है इसलिए कृपया एक कारखाने के उपयोग पर विचार करें। यहां आपके पास एक अच्छा कारखाना उदाहरण है ।

__new__ स्थैतिक वर्ग विधि है, जबकि __init__ उदाहरण विधि है। __new__ को पहले उदाहरण बना दिया है, इसलिए __init__ इसे आरंभ कर सकता है। ध्यान दें कि __init__ self को पैरामीटर के रूप में लेता है जब तक आप उदाहरण बनाते हैं तब तक कोई self नहीं होता है

अब, मैं इकट्ठा, कि आप पायथन में एकलटन पैटर्न को लागू करने की कोशिश कर रहे हैं ऐसा करने के कुछ तरीके हैं

साथ ही, पायथन 2.6 के रूप में, आप वर्ग सज्जाकारों का उपयोग कर सकते हैं।

 def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass: ... 

सबसे प्रसिद्ध ओ ओ भाषाओं में, कुछ SomeClass(arg1, arg2) तरह एक अभिव्यक्ति एक नया उदाहरण आवंटित करेगा, उदाहरण के गुणों को शुरू करने, और फिर इसे वापस लौटाएगा।

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

पायथन का __new__ कुछ ज्यादा नहीं है और "एक नया आवंटन आवंटन भाग" के समान प्रति-वर्ग अनुकूलन से कुछ भी कम नहीं है। बेशक यह आपको एक असामान्य चीज़ों को करने की अनुमति देता है जैसे कि किसी नए आवंटन के बजाय एक मौजूदा उदाहरण लौटाए। इसलिए पायथन में, हमें वास्तव में आवंटन को शामिल करने के रूप में इस हिस्से के बारे में नहीं सोचना चाहिए; हम सभी की जरूरत है कि __new__ कहीं से एक उपयुक्त उदाहरण के साथ आता है

लेकिन यह अभी भी नौकरी का आधा हिस्सा है, और अजगर सिस्टम को पता करने के लिए कोई रास्ता नहीं है कि कभी-कभी आप दूसरे आधे नौकरी ( __init__ ) बाद में चलाना चाहते हैं और कभी-कभी आप नहीं करते हैं। यदि आप उस व्यवहार को चाहते हैं, तो आपको इतना स्पष्ट रूप से कहना होगा।

अक्सर, आप रिफैक्टर कर सकते हैं ताकि आपको केवल __new__ आवश्यकता __new__ , या तो आपको __new__ आवश्यकता नहीं है, या इससे पहले कि __init__ पहले से ही प्रारंभिक ऑब्जेक्ट पर भिन्न तरीके से व्यवहार करता है। लेकिन अगर आप वास्तव में चाहते हैं, तो पायथन वास्तव में आपको "नौकरी" को फिर से परिभाषित करने की अनुमति देता है, ताकि कुछ SomeClass(arg1, arg2) जरूरी नहीं कि __new__ __init__ बाद ऐसा करने के लिए, आपको एक __call__ बनाने की जरूरत है, और इसकी __call__ विधि को परिभाषित करें।

एक मेटैक्लास सिर्फ एक कक्षा का वर्ग है और क्लास __call__ विधि नियंत्रण क्या होता है जब आप क्लास के उदाहरण कॉल करते हैं तो एक __call__ ' __call__ विधि का नियंत्रण होता है जब आप किसी क्लास को कॉल करते हैं; यानी यह आपको इंस्टॉलेशन-क्रिएशन मैकिनिज्म को शुरू से खत्म करने के लिए फिर से परिभाषित करने की अनुमति देता है। यह वह स्तर है, जिस पर आप सबसे सुंदर रूप से एक पूरी तरह से गैर-मानक उदाहरण निर्माण प्रक्रिया को लागू कर सकते हैं जैसे सिंगलटन पैटर्न। वास्तव में, कम से कम 10 लाइनों के कोड के साथ आप Singleton मेटाकल्स को लागू कर सकते हैं, जिससे आपको __new__ साथ __new__ करने की ज़रूरत नहीं है, और किसी अन्य सामान्य वर्ग को सिर्फ __metaclass__ = Singleton जोड़ने के द्वारा सिंगलटन में बदल सकता है!

 class Singleton(type): def __init__(self, *args, **kwargs): super(Singleton, self).__init__(*args, **kwargs) self.__instance = None def __call__(self, *args, **kwargs): if self.__instance is None: self.__instance = super(Singleton, self).__call__(*args, **kwargs) return self.__instance 

हालांकि यह वास्तव में इस स्थिति के लिए वास्तव में warranted की तुलना में गहरा जादू है!

दस्तावेज उद्धृत करने के लिए:

विशिष्ट कार्यान्वयन, "सुपर (वर्तमान क्लास, सीएलएस) .__ नई __ (सीएलएस,, …)" का उपयोग करके सुपरक्लस के __ एनयूयूडी () विधि को उपयुक्त तर्कों के साथ वर्ग के एक नए उदाहरण बनाते हैं और आवश्यकतानुसार नए बनाए गए उदाहरण को संशोधित करते हैं। इसे वापस करने से पहले

यदि __new __ () सीएल की एक आवृत्ति वापस नहीं करता है, तो नया उदाहरण __init __ () विधि लागू नहीं किया जाएगा।

__new __ () मुख्य रूप से उदाहरण निर्माण को अनुकूलित करने के लिए अपरिवर्तनीय प्रकार (जैसे इंट, स्ट्रॉ, या ट्यूपल) के उपवर्गों को अनुमति देने के लिए है।

मुझे पता है कि यह सवाल काफी पुराना है लेकिन मेरे पास एक समान समस्या थी। निम्नलिखित मैं क्या चाहता था:

 class Agent(object): _agents = dict() def __new__(cls, *p): number = p[0] if not number in cls._agents: cls._agents[number] = object.__new__(cls) return cls._agents[number] def __init__(self, number): self.number = number def __eq__(self, rhs): return self.number == rhs.number Agent("a") is Agent("a") == True 

मैंने इस पृष्ठ को एक संसाधन के रूप में इस्तेमाल किया http://infohost.nmt.edu/tcc/help/pubs/python/web/new-new-method.html

मुझे लगता है कि इस प्रश्न का सरल उत्तर यह है कि, यदि __new__ एक मान देता है जो वर्ग के समान प्रकार है, __init__ फ़ंक्शन निष्पादित होता है, अन्यथा यह नहीं होगा। इस मामले में आपका कोड A._dict('key') देता है जो क्लास के समान वर्ग है, इसलिए __init__ को निष्पादित किया जाएगा।

जब __new__ एक ही कक्षा का __new__ देता है, __init__ वापस लौटा वस्तु पर चला जाता है। Ie आप चलने से __init__ को रोकने के लिए __new__ का उपयोग नहीं कर सकते। यहां तक ​​कि अगर आप __new__ से पहले बनाई गई वस्तु को वापस __new__ , तो यह दोहरा (ट्रिपल, इत्यादि …) __new__ द्वारा दोबारा आरंभ किया जाएगा।

यहां सिंगलटन पैटर्न के लिए सामान्य दृष्टिकोण दिया गया है जो उपरोक्त vartec उत्तर को बढ़ाता है और इसे ठीक करता है:

 def SingletonClass(cls): class Single(cls): __doc__ = cls.__doc__ _initialized = False _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Single, cls).__new__(cls, *args, **kwargs) return cls._instance def __init__(self, *args, **kwargs): if self._initialized: return super(Single, self).__init__(*args, **kwargs) self.__class__._initialized = True # Its crucial to set this variable on the class! return Single 

पूरी कहानी यहां है

एक अन्य दृष्टिकोण, जो वास्तव में __new__ शामिल है __new__ का उपयोग करना है:

 class Singleton(object): __initialized = False def __new__(cls, *args, **kwargs): if not cls.__initialized: cls.__init__(*args, **kwargs) cls.__initialized = True return cls class MyClass(Singleton): @classmethod def __init__(cls, x, y): print "init is here" @classmethod def do(cls): print "doing stuff" 

कृपया ध्यान दें, इस दृष्टिकोण से आपको @classmethod साथ अपने सभी तरीकों को सजाने की ज़रूरत है, क्योंकि आप कभी भी MyClass किसी भी वास्तविक उदाहरण का उपयोग नहीं करेंगे।

 class M(type): _dict = {} def __call__(cls, key): if key in cls._dict: print 'EXISTS' return cls._dict[key] else: print 'NEW' instance = super(M, cls).__call__(key) cls._dict[key] = instance return instance class A(object): __metaclass__ = M def __init__(self, key): print 'INIT' self.key = key print a1 = A('aaa') a2 = A('bbb') a3 = A('aaa') 

आउटपुट:

 NEW INIT NEW INIT EXISTS 

एनबी एक साइड इफेक्ट के रूप में M._dict प्रॉपर्टी स्वचालित रूप से A से A रूप में सुलभ हो जाती है, इसलिए सावधानी बरतें कि इसे संयोगवश रूप से अधिलेखित न करें।

__new__ को एक क्लास का एक नया, रिक्त उदाहरण देना चाहिए। तब __init__ को उस उदाहरण को प्रारंभ करने के लिए कहा जाता है। आप __new__ के "नया" मामले में __init__ को नहीं बुला रहे हैं, इसलिए इसे आपके लिए बुलाया जा रहा है। कोड जो __new__ को बुला रहा है, __new__ नज़र नहीं रखता है कि क्या __new__ को किसी विशेष उदाहरण पर बुलाया गया है या न ही, यह इसलिए करना चाहिए क्योंकि आप यहाँ कुछ बहुत ही असामान्य कर रहे हैं।

आप यह इंगित करने के लिए __init__ फ़ंक्शन में ऑब्जेक्ट के लिए एक विशेषता जोड़ सकते हैं कि यह प्रारंभिक है। __init__ में पहली चीज के रूप में उस विशेषता के अस्तित्व की जांच करें और यदि आगे बढ़े तो आगे बढ़ें।

इसमें गहराई से गहराई से!

CPython में एक जेनेरिक क्लास का type और इसका बेस क्लास Object (जब तक आप किसी अन्य बेस क्लास को मेटाक्लास जैसी स्पष्ट रूप से परिभाषित नहीं करते हैं)। निम्न स्तर की कॉल का अनुक्रम यहां पाये जा सकते हैं । पहली विधि जिसे type_call कहा जाता है, उसके बाद tp_new और उसके बाद tp_init कॉल tp_init

यहां दिलचस्प हिस्सा यह है कि tp_new Object (बेस क्लास) नई विधि Object को कॉल object_new जो एक tp_alloc ( PyType_GenericAlloc ) करता है जो वस्तु के लिए मेमोरी आवंटित करता है 🙂

उस बिंदु पर ऑब्जेक्ट मेमोरी में बनाया जाता है और फिर __init__ विधि कहलाती है। यदि __init__ को आपकी कक्षा में लागू नहीं किया गया है तो object_init को बुलाया जाता है और यह कुछ नहीं करता 🙂

तब type_call सिर्फ ऑब्जेक्ट देता है जो आपके वेरिएबल से जुड़ा होता है।

इस दस्तावेज़ का जिक्र करते हुए :

जब अपरिवर्तनीय अंतर्निहित प्रकार के उप-वर्गों जैसे संख्याएं और तार, और कभी-कभी अन्य स्थितियों में, स्थैतिक पद्धति नया काम में आता है नया उदाहरण निर्माण में पहला कदम है, init से पहले शुरू किया।

नई विधि को कक्षा के साथ अपनी पहली तर्क के रूप में कहा जाता है; इसकी ज़िम्मेदारी उस कक्षा के एक नए उदाहरण को वापस करना है।

इसकी तुलना init : init को एक उदाहरण के साथ अपनी पहली तर्क के रूप में कहा जाता है, और यह कुछ भी वापस नहीं करता; इसकी जिम्मेदारी इस उदाहरण को प्रारंभ करना है।

ऐसी परिस्थिति होती है जहां एक नया उदाहरण init को कॉल किए बिना बनाया जाता है (उदाहरण के लिए जब एक अचार से उदाहरण लोड किया जाता है) नए कॉल किए बिना एक नया उदाहरण बनाने का कोई तरीका नहीं है (हालांकि कुछ मामलों में आप बेस क्लास के नए कॉल करने के साथ भाग ले सकते हैं)

आप क्या हासिल करना चाहते हैं, इसके बारे में सिंगलटन पैटर्न के बारे में एक ही डॉक्टर की जानकारी भी है

 class Singleton(object): def __new__(cls, *args, **kwds): it = cls.__dict__.get("__it__") if it is not None: return it cls.__it__ = it = object.__new__(cls) it.init(*args, **kwds) return it def init(self, *args, **kwds): pass 

आप डेकोरेटर का उपयोग करते हुए पीईपी 318 से भी इस कार्यान्वयन का उपयोग कर सकते हैं

 def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass: ... 

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

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

__init__ को __new__ बाद कहा जाता है ताकि जब आप इसे उप-वर्ग में ओवरराइड कर लें, तो आपके जोड़े गए कोड को अभी भी कहा जाएगा।

यदि आप एक वर्ग को उप-वर्ग की कोशिश कर रहे हैं जो पहले से ही एक __new__ , तो इसका कोई अनजान नहीं हो सकता है __init__ को आदत डालकर और कॉल को उप-क्लास __new__ सकता है। __new__ बाद __init__ फोन करने के इस सम्मेलन की उम्मीद के अनुसार काम करने में यह मदद करता है।

__init__ अभी भी किसी भी पैरामीटर के लिए अनुमति देने की आवश्यकता है जो सुपरक्लस __new__ आवश्यकता है, लेकिन ऐसा करने में विफल सामान्यतः एक स्पष्ट रनटाइम त्रुटि पैदा होगी। और __new__ को स्पष्ट रूप से *args और '** kw' के लिए अनुमति देना चाहिए, यह स्पष्ट करने के लिए कि विस्तार ठीक है।

व्यवहार के कारण मूल पोस्टर का वर्णन, यह समान रूप से विरासत के समान स्तर पर समान कक्षा में दोनों __new__ और __init__ दोनों के पास गलत रूप है।

@ एंटोनी हच्किंस के लिए एक अपडेट का जवाब, आप शायद मेटाटिप के प्रत्येक वर्ग के उदाहरणों का एक अलग शब्दकोश चाहते हैं, जिसका अर्थ है कि आपको मेटाक्लास में एक __इनट_ विधि होना चाहिए, ताकि आप अपनी कक्षा ऑब्जेक्ट को उस डिक्शनरी के साथ आरंभ कर सकें, जो कि सभी कक्षाओं में वैश्विक हो ।

 class MetaQuasiSingleton(type): def __init__(cls, name, bases, attibutes): cls._dict = {} def __call__(cls, key): if key in cls._dict: print('EXISTS') instance = cls._dict[key] else: print('NEW') instance = super().__call__(key) cls._dict[key] = instance return instance class A(metaclass=MetaQuasiSingleton): def __init__(self, key): print 'INIT' self.key = key print() 

मैंने आगे बढ़कर मूल कोड को एक __init__ विधि के साथ अद्यतन किया और वाक्यविन्यास को पायथन 3 नेशन (कोई आरजीएल को super और मेटाक्लास के बजाय क्लास तर्कों के बजाय एक विशेषता के रूप में) बदल दिया।

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

हालांकि, मैं थोड़ा उलझन में हूं कि __init__ हमेशा __new__ बाद क्यों कहा जाता है

इसके अलावा अन्य कोई कारण नहीं है कि यह सिर्फ इस तरह से किया जाता है। __new__ का कक्षा आरंभ करने की जिम्मेदारी नहीं है, कुछ अन्य विधि ( __call__ , संभवत: – मुझे निश्चित रूप से नहीं पता है)।

मुझे यह उम्मीद नहीं थी। क्या कोई मुझे बता सकता है कि यह क्यों हो रहा है और मैं यह कार्यक्षमता अन्यथा कैसे लागू करूं? (कार्यान्वयन को __new__ में डालने के अलावा जो काफी __new__ लगता है)।

यदि आप पहले से ही आरम्भ हो चुके हैं, तो आप कुछ भी नहीं कर सकते हैं, या आप एक नया __call__ साथ एक नया __call__ जो केवल नए उदाहरणों पर __init__ को कॉल करता है, और अन्यथा सिर्फ __new__(...) लौटाता है।