2009-07-13 21 views
13

पायथन 2 के लिए अपेक्षाकृत नया होने के नाते, मुझे अनिश्चितता है कि मेरी कक्षा फ़ाइलों को सबसे अधिक 'पायथनिक' तरीके से व्यवस्थित करने के लिए सबसे अच्छा तरीका है। मैं यह नहीं पूछूंगा लेकिन इस तथ्य के लिए कि पाइथन को उन चीजों को करने के कुछ तरीके हैं जो मुझे उन भाषाओं से अपेक्षा करने के लिए बहुत अलग हैं जो मैं उपयोग करता हूं।क्लास गुणों, कन्स्ट्रक्टर तर्क और सबक्लास कन्स्ट्रक्टर डिफ़ॉल्ट को व्यवस्थित करने का अधिकांश "पायथनिक" तरीका?

प्रारंभ में, मैं सिर्फ कक्षाओं का इलाज किया गया था कैसे मैं आमतौर पर सी # या PHP, जो निश्चित रूप से बनाया मुझे हर जगह जब मैं अंत में परिवर्तनशील मूल्यों पकड़ लिया की खोज की यात्रा में उन्हें इलाज चाहते हैं:

class Pants(object): 
    pockets = 2 
    pocketcontents = [] 

class CargoPants(Pants): 
    pockets = 200 

p1 = Pants() 
p1.pocketcontents.append("Magical ten dollar bill") 
p2 = CargoPants() 

print p2.pocketcontents 

ओह! उस की उम्मीद नहीं थी!

मैंने अपनी कक्षाओं को व्यवस्थित करने के तरीके के बारे में संकेतों के लिए वेब पर और अन्य परियोजनाओं के लिए कुछ स्रोतों के माध्यम से बहुत समय बिताया है, और मैंने देखा कि चीजों में से एक यह था कि लोग अपने बहुत सारे उदाहरण घोषित करते हैं परिवर्तनीय - परिवर्तनीय या अन्यथा - कन्स्ट्रक्टर में, और काफी मोटे तौर पर डिफ़ॉल्ट कन्स्ट्रक्टर तर्कों को ढेर करते हैं।

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

class ClassWithLotsOfAttributes(object): 
    def __init__(self, jeebus, coolness='lots', python='isgoodfun', 
      pythonic='nebulous', duck='goose', pants=None, 
      magictenbucks=4, datawad=None, dataload=None, 
      datacatastrophe=None): 

     if pants is None: pants = [] 
     if datawad is None: datawad = [] 
     if dataload is None: dataload = [] 
     if datacatastrophe is None: datacatastrophe = [] 
     self.coolness = coolness 
     self.python = python 
     self.pythonic = pythonic 
     self.duck = duck 
     self.pants = pants 
     self.magictenbucks = magictenbucks 
     self.datawad = datawad 
     self.dataload = dataload 
     self.datacatastrophe = datacatastrophe 
     self.bigness = None 
     self.awesomeitude = None 
     self.genius = None 
     self.fatness = None 
     self.topwise = None 
     self.brillant = False 
     self.strangenessfactor = 3 
     self.noisiness = 12 
     self.whatever = None 
     self.yougettheidea = True 

class Dog(ClassWithLotsOfAttributes): 
    def __init__(self, coolness='lots', python='isgoodfun', pythonic='nebulous', duck='goose', pants=None, magictenbucks=4, datawad=None, dataload=None, datacatastrophe=None): 
     super(ClassWithLotsOfAttributes, self).__init__(coolness, python, pythonic, duck, pants, magictenbucks, datawad, dataload, datacatastrophe) 
     self.noisiness = 1000000 

    def quack(self): 
     print "woof" 

हल्के मूर्खता एक तरफ (मैं वास्तव में अपने आप को जब ये कृत्रिम उदाहरण कक्षाओं खाना पकाने में मदद नहीं कर सकते हैं), यह मानते हुए मैं एक वास्तविक दुनिया है यह कई विशेषताओं के साथ वर्गों में से एक सेट के लिए की जरूरत है, मैं लगता है मेरे सवालों हैं:

  • सबसे, उह, 'pythonic' है कि कई विशेषताओं के साथ एक वर्ग घोषित करने के तरीका क्या है? यदि डिफ़ॉल्ट अपरिवर्तनीय है, तो अल्पा Pants.pockets, या उन्हें कन्स्ट्रक्टर, ala ClassWithLotsOfAttributes.noisiness में रखना बेहतर है, तो उन्हें कक्षा के खिलाफ रखना सबसे अच्छा है?

  • क्या कुत्ते में सभी उपclass कन्स्ट्रक्टर तर्कों के लिए डिफ़ॉल्ट को फिर से शुरू करने की आवश्यकता को खत्म करने का कोई तरीका है .__ init__? क्या मुझे भी कई तर्कों को डिफ़ॉल्ट रूप से शामिल करना चाहिए?

+0

+1 आपके उदाहरण विशेषताओं से प्यार होगा। इसके अलावा, अच्छा सवाल है। – balpha

उत्तर

4
  • गुण उदाहरण के लिए उदाहरण से अलग अलग होंगे, तो उन्हें उदाहरण विशेषता यानी स्वयं किसी और का उपयोग कर उन्हें __init__ में बनाते अगर वे एक निरंतर की तरह वर्ग उदाहरणों के बीच साझा किया की जरूरत बनाने के लिए, उन्हें कक्षा स्तर पर रखें।

  • अपने वर्ग वास्तव में __init__ में पारित करने के लिए है, तो कई तर्क की जरूरत है, प्राप्त वर्ग उपयोग तर्क सूची और कीवर्ड तर्क जैसे जाने

class Dog(ClassWithLotsOfAttributes): 
    def __init__(self, *args , **kwargs): 
     super(ClassWithLotsOfAttributes, self).__init__(*args , **kwargs) 
     self.coolness = "really cool!!!
  • कुछ महत्वपूर्ण लोगों को छोड़कर सभी चर में उत्तीर्ण होने की कोई जरूरत नहीं है, __init__ में, वर्ग कुछ चूक मान सकते हैं और उपयोगकर्ता यदि आवश्यक हो तो उन्हें पर बाद में बदल सकते हैं।
  • टैब के बजाय 4 रिक्त स्थान का उपयोग करें।

  • यदि आप कुत्ते के लिए एक अतिरिक्त आर्ग काटने को जोड़ने के लिए, और आर्ग पुराने कीवर्ड भी

class CoolDog(ClassWithLotsOfAttributes): 
    def __init__(self, bite, *args , **kwargs): 
     self.old = kwargs.pop('old', False) # this way we can access base class args too 
     super(ClassWithLotsOfAttributes, self).__init__(*args , **kwargs) 
     self.bite = bite 
     self.coolness = "really really cool!!!

विभिन्न तरीकों की जरूरत है आप useCoolDog

CoolDog(True) 
CoolDog(True, old=False) 
CoolDog(bite=True, old=True) 
CoolDog(old=True, bite=False) 
+0

कुछ स्वरूपण विशेषज्ञ होगा, कोड को सही ढंग से प्रारूपित करें? –

+0

ओह मुझे नहीं पता था कि आप उस तरह * args और ** kwargs का उपयोग कर सकते हैं! 'शीतलता' को निश्चित रूप से 'वास्तव में शांत' करने की आवश्यकता है! :) – Shabbyrobe

+0

भी, उस मामले के बारे में क्या है जहां कुत्ते .__ init__ को अतिरिक्त कन्स्ट्रक्टर तर्क जोड़ने की आवश्यकता है? def__init __ (स्वयं, पैर = 4, * args, ** kwargs) इसके बारे में जाने का सही तरीका है? – Shabbyrobe

-1

यह संभव है कि आप तोड़ सकते हैं कक्षाओं में आपके विशाल वर्ग नीचे जो प्रत्येक केवल एक साधारण कार्य करता है। आमतौर पर कक्षाओं को इस कई विशेषताओं की आवश्यकता नहीं होती है।

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

आपको उन्हें self पर असाइन करना चाहिए, न कि क्लास गुणों के रूप में। अंतर ध्यान दें:

class Class1(object): 
    attr1 = 'abc' 

class Class2(object): 
    def __init__(self): 
     self.attr1 = 'abc' 

Class1.attr1 # returns 'abc' 
c = Class1() 
c.attr1 # Also returns 'abc' 
Class1.attr1 = 'def' 
c.attr1 # Returns 'def'! 
c.attr1 = 'abc' # Now the c instance gets its own value and will show it 
       # independently of what Class1.attr1 is. This is the same 
       # behavior that Class2 exhibits from the start. 
संबंधित मुद्दे