2010-02-07 13 views
18

मैं एक वर्ग है:से बचें एक उपवर्ग में सभी तर्कों को निर्दिष्ट

class A(object): 
    def __init__(self,a,b,c,d,e,f,g,...........,x,y,z) 
     #do some init stuff 

और मैं एक उपवर्ग जो एक अतिरिक्त आर्ग (पिछले W)

class B(A): 
    def __init__(self.a,b,c,d,e,f,g,...........,x,y,z,W) 
     A.__init__(self,a,b,c,d,e,f,g,...........,x,y,z) 
     self.__W=W 

यह सब लिखने के लिए गूंगा लगता है की जरूरत है यह बॉयलर-प्लेट कोड, उदाहरण के लिए B के सीटीआर से A के सीटीआर तक सभी तर्कों को पारित करना, तब से A के सीटीआर में प्रत्येक परिवर्तन B के कोड में दो अन्य स्थानों पर लागू होना चाहिए।

मुझे लगता है कि पाइथन में ऐसे मामलों को संभालने के लिए कुछ मुहावरे है जो मुझे अनजान हैं। क्या मुझे आपसे सही दिशा निर्देशन मिलेगा?

मेरे सबसे अच्छा कूबड़, एक के लिए कॉपी-ctor का एक प्रकार है और जब पिता का एक उदाहरण दिया तो

class B(A): 
    def __init__(self,instanceOfA,W): 
     A.__copy_ctor__(self,instanceOfA) 
     self.__W=W 

इस में बी के कोड बदलने के बाद से मैं हमेशा उपवर्ग बनाने मेरी आवश्यकताओं के अनुरूप होता है कक्षा, हालांकि मुझे यकीन नहीं है कि यह संभव है ...

+0

आपके पास यह है कि कई तर्क, मैं स्थितीय तर्कों का उपयोग नहीं होता है, लेकिन उन सब को तो/उनमें से ज्यादातर kwargs के रूप में और py3 '*' वाक्यविन्यास 'def __initi __ (arg1, arg2, * kwarg1 = ..., ..., kwargx = ..., w = ...) का उपयोग करें kwargs को मजबूर करने के लिए (= पर भरोसा नहीं है आदेश)। 'Def __init __ (स्वयं, arg1, arg2, *, ** kwargs) का उपयोग करना छोटा है, लेकिन मुझे यह पसंद नहीं है क्योंकि आईडीआईएस में कोड को पूरा करने में गड़बड़ है जैसे कि पिचर्म। स्क्रीन कचरे के अलावा, सभी kwargs लिखने में क्या नुकसान है? आपको वैसे भी उन्हें दस्तावेज़ों में दस्तावेज करना होगा ... –

उत्तर

17

यह देखते हुए कि तर्क या तो नाम से या स्थिति द्वारा पारित किया जा सकता है, मैं कोड चाहते ऐसी परिस्थितियों में जहां कुछ या सभी तर्क __init__ पर पास किए गए हैं, वे डिफ़ॉल्ट मान हैं, यह सबक्लास में __init__ विधि हस्ताक्षर दोहराने से बचने के लिए उपयोगी हो सकता है।

इन मामलों में, __init__ एक और तरीका है, जो उपवर्गों ओवरराइड कर सकते हैं करने के लिए किसी भी अतिरिक्त तर्क पारित कर सकते हैं:

class A(object): 
    def __init__(self, a=1, b=2, c=3, d=4, *args, **kwargs): 
     self.a = a 
     self.b = b 
     # … 
     self._init_extra(*args, **kwargs) 

    def _init_extra(self): 
     """ 
     Subclasses can override this method to support extra 
     __init__ arguments. 
     """ 

     pass 


class B(A): 
    def _init_extra(self, w): 
     self.w = w 
+0

मुझे यह विचार पसंद है, लेकिन मुझे नहीं लगता कि उदाहरण काम करता है। चूंकि '* ए 'के कारण' a' का कारण बनता है [** ** tuple ** प्राप्त करें] (http://docs.python.org/tutorial/controlflow.html?highlight=kwargs#keyword-arguments),' a' doesn ' टी 'पॉप()' विधि नहीं है। 'ए' को पहले सूची में परिवर्तित करने की आवश्यकता है। साथ ही, यदि सभी तर्क नाम से पारित होते हैं, तो 'ए' खाली है (इसलिए आप इसे 'पॉप() 'नहीं कर सकते हैं)। –

+0

एर, मेरी पिछली टिप्पणी में अंतिम वाक्य को कभी भी न छोड़ें। –

+1

'विशेषता त्रुटि:' tuple 'ऑब्जेक्ट में कोई विशेषता नहीं है' pop'' –

0

क्या आप ऐसा कुछ चाहते हैं?

class A(object): 
    def __init__(self, a, b, c, d, e, f, g): 
     # do stuff 
     print a, d, g 

class B(A): 
    def __init__(self, *args): 
     args = list(args) 
     self.__W = args.pop() 
     A.__init__(self, *args) 
+0

अच्छी तरह से, यह बहुत सरल संस्करण के लिए काम करता है। लेकिन अब बी किसी भी संख्या में तर्क लेता है (कम सीमित) ... क्या कुछ और मूर्ख नहीं है? – olamundo

+1

बी केवल किसी भी प्रकार की तर्क लेता है; यह ए को कॉल करता है और यदि ए को गलत नंबर मिलता है तो यह 'TypeError' बढ़ाएगा। यदि आप कामना करते हैं तो आप स्पष्ट रूप से तर्कों की संख्या की जांच कर सकते हैं। मैं शायद उत्पादन कोड में होगा। –

+0

यदि आपको तर्कों की गलत संख्या मिलती है, तो आप वैसे भी टाइपएरर उठाएंगे। – Dinoboff

7

संपादित करें: मैट सुझाव के आधार पर, और एक स्थितीय तर्क दृष्टिकोण फिर से gnibbler की चिंता का समाधान करने के लिए; Matt's answer रूप
एक ही विचार है, बजाय super() का उपयोग कर: आप यह सुनिश्चित करें कि अतिरिक्त उपवर्ग विशेष तर्क Alex's answer करने के लिए निर्दिष्ट-समान की जा रही है बनाने के लिए जाँच कर सकते हैं:

class B(A): 
    def __init__(self, *args, **kwargs): 
    try: 
     self._w = kwargs.pop('w') 
    except KeyError: 
     pass 
    super(B,self).__init__(*args, **kwargs) 

>>> b = B(1,2,w=3) 
>>> b.a 
1 
>>> b.b 
2 
>>> b._w 
3 

मूल जवाब।

उपयोग super() सुपर क्लास के __init__() विधि कॉल करने के लिए, तो उपवर्ग initialising जारी रखने के लिए:

class B(A): 
    def __init__(self, *a, **k): 
     if 'W' in k: 
     w = k.pop('W') 
     else: 
     w = a.pop() 
     A.__init__(self, *a, **k) 
     self._W = w 
+0

इस समाधान के लिए आवश्यक है कि डब्ल्यू को पहले तर्क या नाम के रूप में पारित किया जाना है। सवाल यह आखिरी तर्क –

+0

@gnu nibbler के रूप में है: आपकी टिप्पणी के लिए धन्यवाद। मैंने इस चिंता को हल करने के लिए अपना जवाब संपादित किया है; एलेक्स ने कई घंटों पहले पोस्ट किया था :-) – bernie

2

:

class A(object): 
    def __init__(self, a, b): 
    self.a = a 
    self.b = b 

class B(A): 
    def __init__(self, w, *args): 
    super(B,self).__init__(*args) 
    self.w = w 
संबंधित मुद्दे