2010-01-29 12 views
112

संभव डुप्लिकेट:
What is a clean, pythonic way to have multiple constructors in Python?पायथन में एकाधिक रचनाकार?

यह अलग हस्ताक्षरों के साथ, पायथन में एक से अधिक निर्माताओं को परिभाषित करना संभव नहीं है? यदि नहीं, तो इसके आसपास होने का सामान्य तरीका क्या है?

उदाहरण के लिए, मान लीजिए कि आप एक वर्ग City

मैं someCity = City() या someCity = City("Berlin") है, जिसकी पहली सिर्फ एक डिफ़ॉल्ट नाम मूल्य देता है, और दूसरा यह परिभाषित करता है कहने में सक्षम होना चाहते हैं परिभाषित करने के लिए चाहता था करते हैं।

+2

मुझे इस सवाल के बारे में सोच है - http://stackoverflow.com/questions/682504/what-is-a-clean-pythonic-way-to-have-multiple -कॉन्स्ट्रक्टर्स-इन-पायथन – Gant

+0

सर्वश्रेष्ठ: [तर्क प्रकार के आधार पर '__init__' विधि को अधिभार कैसे करें?] (https://stackoverflow.com/questions/141545/how-to-overload-init-method-based-on- तर्क-प्रकार) –

उत्तर

143

जावा के विपरीत, आप एकाधिक रचनाकारों को परिभाषित नहीं कर सकते हैं। हालांकि, यदि कोई पास नहीं हुआ है तो आप डिफ़ॉल्ट मान को परिभाषित कर सकते हैं।

def __init__(self, city="Berlin"): 
    self.city = city 
2

सबसे आसान तरीका कीवर्ड तर्क के माध्यम से है:

class City(): 
    def __init__(self, city=None): 
    pass 

someCity = City(city="Berlin") 

यह सुंदर बुनियादी सामान, हो सकता है the python docs को देखो है?

+0

टिप्पणियों में टाइपो; यह भी सवाल नहीं है - उसने टाइपों पर स्विच करने के बारे में पूछा, उसने सिर्फ एक बुरा उदाहरण दिया। – pavpanchekha

+1

@pavpanchekha: यह वही है जो पूछा गया था। बेशक 'स्वयं' गायब होने के अलावा। – SilentGhost

+5

@ जैक, आपका उदाहरण वास्तव में कहीं भी 'शहर' को संग्रहीत नहीं करता है, इसलिए एक नौसिखिया के लिए यह एक बहुत भ्रमित उत्तर हो सकता है। –

2

उदाहरण के लिए आप दे दी है, उपयोग डिफ़ॉल्ट मान:

class City: 
    def __init__(self, name="Default City Name"): 
     ... 
    ... 

सामान्य तौर पर, आप दो विकल्प हैं:

1) क्या if - elif ब्लॉक प्रकार के आधार पर:

def __init__(self, name): 
    if isinstance(name, str): 
     ... 
    elif isinstance(name, City): 
     ... 
    ... 

2) बतख टाइपिंग का उपयोग करें --- यानी, मान लें कि आपकी कक्षा का उपयोगकर्ता बुद्धिमानी से इसका उपयोग करने के लिए पर्याप्त बुद्धिमान है। यह आमतौर पर पसंदीदा विकल्प है।

+0

@ भूत डिफ़ॉल्ट मान .... उम ... मुझे लगता है कि यह है। मुद्दा लेना। मैंने इसे वोट क्यों दिया? आह बकवास, वोट अब बदलने के लिए बहुत पुराना है। –

140

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

class C(object): 

    def __init__(self, fd): 
     # Assume fd is a file-like object. 
     self.fd = fd 

    @classmethod 
    def fromfilename(cls, name): 
     return cls(open(name, 'rb')) 

# Now you can do: 
c = C(fd) 
# or: 
c = C.fromfilename('a filename') 

सूचना उन सभी classmethods अब भी वही __init__ के माध्यम से जाना है, लेकिन classmethods का उपयोग कर याद करने के लिए अधिक से अधिक सुविधाजनक हो सकता है कि कौन से कीवर्ड तर्क के संयोजन __init__ काम करने के लिए।

isinstance जिससे बचना है, क्योंकि अजगर का बतख टाइपिंग यह मुश्किल यह पता लगाने की क्या वस्तु की तरह वास्तव में में पारित किया गया था बनाता है उदाहरण के लिए:। यदि आप या तो एक फ़ाइल नाम या एक फ़ाइल जैसी वस्तु आप isinstance(arg, file) उपयोग नहीं कर सकते क्योंकि ले जाना चाहते हैं कई फाइल-जैसी ऑब्जेक्ट्स हैं जो file (जैसे urllib से लौटाए गए, या स्ट्रिंगियो, या ...) को उपclass नहीं करते हैं। यह आमतौर पर एक बेहतर विचार है कि कॉलर आपको अलग-अलग कीवर्ड तर्कों का उपयोग करके स्पष्ट रूप से बताए कि किस तरह का ऑब्जेक्ट था।

+0

जैसा कि आप कहते हैं, यह एक शानदार तरीका है यदि आपको विभिन्न प्रकार के तर्कों को पारित करने की आवश्यकता है। उन मामलों में मैं एक बहुत ही बुनियादी '__init__' का उपयोग करता हूं और प्रत्येक मामले के लिए एक से अधिक कक्षा विधि बना देता हूं। – zekel

2

जैक एम।सही है, यह इस तरह से कार्य करें:

>>> class City: 
...  def __init__(self, city=None): 
...   self.city = city 
...  def __repr__(self): 
...   if self.city: return self.city 
...   return '' 
... 
>>> c = City('Berlin') 
>>> print c 
Berlin 
>>> c = City() 
>>> print c 

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