अजगर निर्माणकर्ता और __init__


107

कंस्ट्रक्टरों को वास्तव में "कंस्ट्रक्टर्स" क्यों कहा जाता है? उनका उद्देश्य क्या है और वे कक्षा में विधियों से कैसे भिन्न हैं?

इसके अलावा, वहाँ __init__एक वर्ग में अधिक हो सकता है ? मैंने निम्नलिखित की कोशिश की, क्या कोई परिणाम की व्याख्या कर सकता है?

>>> class test:
    def __init__(self):
        print "init 1"
    def __init__(self):
        print "init 2"

>>> s=test()
init 2

अंत में, __init__एक ऑपरेटर ओवरलोडर है?


41
तकनीकी रूप से, __init__एक प्रारंभिक है । अजगर कंस्ट्रक्टर है __new__। पायथन स्वचालित दो-चरण के आरंभीकरण का उपयोग करता है - __new__एक वैध लेकिन (आमतौर पर) अनपॉप किए गए ऑब्जेक्ट ( boolएक काउंटर-उदाहरण के लिए देखें) देता है, जो तब __init__स्वचालित रूप से इस पर कॉल करता है। यह उन समस्याओं से बचा जाता है जैसे C ++ में आंशिक रूप से निर्मित वस्तुओं के साथ भाषाएं होती हैं - आपके पास पायथन में कभी भी एक नहीं होता (हालांकि यह आंशिक रूप से प्रारंभिक हो सकता है)। आपको लगभग कभी भी दोनों को __new__और __init__एक वर्ग को ओवरराइड करने की आवश्यकता नहीं होगी ।
— टिम डेलाने

2
@TimDelaney: मुझे यकीन नहीं है कि C ++ में आंशिक रूप से निर्मित वस्तुओं के साथ आपका क्या मतलब है।
— सेबस्टियन मच

11
@phresnel C ++ में ऑब्जेक्ट का प्रकार बेस क्लास कंस्ट्रक्टर में बेस क्लास (सबक्लास नहीं) है। आप बेस क्लास कंस्ट्रक्टर में वर्चुअल मेथड नहीं बुला सकते हैं और उपवर्ग कार्यान्वयन को प्रदान करते हैं। जावा में आप बेस क्लास कंस्ट्रक्टर में सबक्लास विधि कह सकते हैं, लेकिन बेस क्लास कंस्ट्रक्टर (और मेथड कॉल) के बाद सबक्लास मेंबर वेरिएबल अपने आप ही इनिशियलाइज़ हो जाएगा । पायथन जैसे दो-चरण के आरंभीकरण वाली भाषाओं में, आप बेस क्लास आरंइज़र में तरीकों को खुशी से कह सकते हैं और व्यवहार को उप-वर्ग (या ओवरराइड) प्रदान कर सकते हैं।
— टिम डेलानी 12

@TimDelaney: आह, स्पष्ट करने के लिए धन्यवाद।
— सेबेस्टियन मच

4
@TimDelaney। मुझे लगता है कि आपकी टिप्पणी को स्वीकृत उत्तर को बदलना चाहिए।
— फ्लेमेंको

जवाबों:


114

पायथन में कोई फ़ंक्शन ओवरलोडिंग नहीं है, जिसका अर्थ है कि आपके पास एक ही नाम के साथ कई कार्य नहीं हो सकते हैं लेकिन विभिन्न तर्क हैं।

आपके कोड उदाहरण में, आप ओवरलोडिंग नहीं कर रहे हैं __init__()। क्या होता है कि दूसरी परिभाषा है rebinds नाम __init__नई विधि के लिए, पहली विधि दुर्गम हो जाता है।

कंस्ट्रक्टर्स के बारे में आपके सामान्य प्रश्न के अनुसार, विकिपीडिया एक अच्छा प्रारंभिक बिंदु है। पायथन-विशिष्ट सामान के लिए, मैं पायथन डॉक्स की अत्यधिक अनुशंसा करता हूं ।


क्या इसका मतलब यह भी है कि स्रोत फ़ाइल को पार्स किया गया है (व्याख्या की गई है) क्रमिक रूप से? क्या मुझे यकीन है कि मैंने जो भी फ़ंक्शन परिभाषित किया है वह बाद में उसी नाम से परिभाषित एक को पहले से अधिलेखित कर सकता है? :( मेरी क्यू मूर्खतापूर्ण लगती है .. इसे जानना चाहिए था
— 0xc0de

4
@ 0xc0de: पायथन में, फ़ंक्शन परिभाषाएँ वास्तव में निष्पादन योग्य कथन हैं और ऊपर से नीचे तक चलती हैं, इसलिए हाँ।
— NPE

1
@ 0xc0de वास्तव में क्या होता है कि वर्ग के निकाय को उसके स्वयं के नामस्थान में निष्पादित किया जाता है, उस नाम स्थान को फिर मेटाक्लस (नाम और आधार के साथ) में पारित किया जाता है। तब फंक्शन की परिभाषाएँ केवल निर्दिष्ट निकाय के साथ एक फ़ंक्शन बना रही हैं और इसे नाम से निर्दिष्ट करती हैं। अंतिम असाइनमेंट वह __init__होगा जो कक्षा में समाप्त होता है।
— आकाशवाणी

64

कंस्ट्रक्टरों को वास्तव में "कंस्ट्रक्टर्स" क्यों कहा जाता है?

कंस्ट्रक्टर (नामित __new__) वर्ग का एक नया उदाहरण बनाता है और लौटाता है। तो C.__new__क्लास विधि क्लास सी के लिए कंस्ट्रक्टर है ।

C.__init__उदाहरण विधि एक विशिष्ट उदाहरण पर कहा जाता है, के बाद यह बनाया जाता है, फोन करने वाले के लिए वापस पारित किया जा रहा से पहले ही आरंभ करने के लिए। तो वह विधि C के नए उदाहरणों के लिए आरंभिक है।

वे कक्षा में विधियों से कैसे भिन्न हैं?

जैसा कि आधिकारिक दस्तावेज __init__ में कहा गया है कि उदाहरण निर्मित होने के बाद कहा जाता है । अन्य विधियाँ इस उपचार को प्राप्त नहीं करती हैं।

उनका उद्देश्य क्या है?

कंस्ट्रक्टर C.__new__का उद्देश्य नए Cउदाहरण के निर्माण के दौरान कस्टम व्यवहार को परिभाषित करना है ।

आरम्भ करने वाले का उद्देश्य इसके बनने C.__init__के Cबाद के प्रत्येक उदाहरण के कस्टम इनिशियलाइज़ेशन को परिभाषित करना है।

उदाहरण के लिए अजगर आपको करने की अनुमति देता है:

class Test(object):
    pass

t = Test()

t.x = 10   # here you're building your object t
print t.x

लेकिन अगर आप चाहते हैं कि हर उदाहरण में 10 के बराबर Testविशेषता हो x, तो आप उस कोड को अंदर रख सकते हैं __init__:

class Test(object):
    def __init__(self):
        self.x = 10

t = Test()
print t.x

प्रत्येक आवृत्ति विधि (किसी वर्ग के विशिष्ट उदाहरण पर कॉल की गई विधि) को इसके पहले तर्क के रूप में आवृत्ति प्राप्त होती है। उस तर्क को पारंपरिक नाम दिया गया है self।

क्लास मेथड्स, जैसे कंस्ट्रक्टर __new__, क्लास को उनके पहले तर्क के रूप में प्राप्त करते हैं।

अब, यदि आप उस xविशेषता के लिए कस्टम मान चाहते हैं जो आपको करना है तो उस मान को तर्क के रूप में पास करें __init__:

class Test(object):
    def __init__(self, x):
        self.x = x

t = Test(10)
print t.x
z = Test(20)
print t.x

मुझे आशा है कि यह आपको कुछ संदेह को दूर करने में मदद करेगा, और जब से आप पहले से ही अन्य सवालों के अच्छे जवाब प्राप्त कर चुके हैं, मैं यहाँ रुकूंगा :)


9

कक्षाएं केवल वस्तुओं को बनाने के लिए ब्लूप्रिंट हैं। कंस्ट्रक्टर कुछ कोड है जो हर बार जब आप एक ऑब्जेक्ट बनाते हैं तो चलाए जाते हैं। इसके लिए दो कंस्ट्रक्टर होने का कोई मतलब नहीं है। क्या होता है कि दूसरा ओवर पहले लिखें।

आप आम तौर पर उनके लिए इसका उपयोग करते हैं, इस तरह से उस वस्तु के लिए चर बनाते हैं:

>>> class testing:
...     def __init__(self, init_value):
...         self.some_value = init_value

तो आप इस वर्ग से इस तरह एक वस्तु बनाने के लिए क्या कर सकते हैं:

>>> testobject = testing(5)

Testobject के पास एक ऑब्जेक्ट होगा जिसे कहा जाएगा some_valueकि इस नमूने में 5 होंगे।

>>> testobject.some_value
5

लेकिन आपको प्रत्येक वस्तु के लिए एक मूल्य निर्धारित करने की आवश्यकता नहीं है जैसे मैंने अपने नमूने में किया था। आप भी ऐसा कर सकते हैं:

>>> class testing:
...     def __init__(self):
...         self.some_value = 5

तो some_value का मान 5 होगा और जब आप ऑब्जेक्ट बनाते हैं तो आपको इसे सेट करने की आवश्यकता नहीं होती है।

>>> testobject = testing()
>>> testobject.some_value
5

>>> और ... मेरे नमूने में वह नहीं है जो आप लिखते हैं। यह कैसे pyshell में दिखेगा ...


कोई बात नहीं, ख़ुशी है कि इससे आपको मदद मिली :)
— निकल्स निल्सन

1

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

def func(): #now func refers to an empty funcion
    pass
...
func=5      #now func refers to the number 5
def func():
    print "something"    #now func refers to a different function

आपकी कक्षा की परिभाषा में, यह सिर्फ बाद में रखता है


0

पायथन में विधि अधिभार की कोई धारणा नहीं है। लेकिन आप वैकल्पिक और कीवर्ड तर्कों को निर्दिष्ट करके एक समान प्रभाव प्राप्त कर सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.