मैं पायथन में एक कक्षा कैसे डिजाइन करूं?


143

मेरे पास पंजे और पैर की उंगलियों का पता लगाने के लिए मेरे पिछले सवालों पर कुछ बहुत बढ़िया मदद है , लेकिन ये सभी समाधान एक समय में केवल एक माप के लिए काम करते हैं।

अब मेरे पास डेटा है जो बंद हैं:

  • लगभग 30 कुत्ते;
  • प्रत्येक में 24 माप होते हैं (कई उपसमूह में विभाजित);
  • प्रत्येक माप में कम से कम 4 संपर्क होते हैं (प्रत्येक पंजा के लिए) और
    • प्रत्येक संपर्क को 5 भागों में विभाजित किया गया है और
    • कई पैरामीटर हैं, जैसे संपर्क समय, स्थान, कुल बल आदि।

वैकल्पिक शब्द

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

मैं यह भी महसूस करता हूं कि हर बार जब मैं कुछ जानकारी प्राप्त करना चाहता हूं तो सभी डेटा को संसाधित करना अजीब होता है । एक बार जब मुझे प्रत्येक पंजा के स्थानों का पता चल जाता है, तो मुझे फिर से गणना करने का कोई कारण नहीं है। इसके अलावा, मैं एक ही कुत्ते के सभी पंजे की तुलना यह निर्धारित करने के लिए करना चाहता हूं कि कौन सा संपर्क किस पंजा (सामने / हिंद, बाएं / दाएं) से संबंधित है। यदि मैं केवल कार्यों का उपयोग जारी रखता हूं तो यह गड़बड़ हो जाएगा।

तो अब मैं सलाह दे रहा हूं कि कैसे कक्षाएं बनाई जाएं जो मुझे अपने डेटा ( एक कुत्ते के ज़िप्ड डेटा से लिंक ) को एक समझदार तरीके से संसाधित करने दें ।


4
आप डेटाबेस का उपयोग करने पर भी विचार कर सकते हैं (जैसे sqlite: docs.python.org/library/sqlite3.html )। आप एक प्रोग्राम लिख सकते हैं जो आपकी विशाल डेटा फ़ाइलों को पढ़ता है और इसे डेटाबेस तालिकाओं में पंक्तियों में परिवर्तित करता है। फिर दूसरे चरण के रूप में आप ऐसे प्रोग्राम लिख सकते हैं जो डेटा को डेटाबेस से बाहर निकालते हैं ताकि आगे का विश्लेषण किया जा सके।
unutbu

आप कुछ मतलब है जैसे मैंने यहाँ पूछा @ubutbu? मैं इसे करने की योजना बना रहा हूं, लेकिन पहले मैं एक अधिक संगठित फैशन में सभी डेटा को संसाधित करने में सक्षम होना चाहता हूं
Ivo Flipse

जवाबों:


434

कैसे एक वर्ग डिजाइन करने के लिए।

  1. शब्द लिखो। आपने ऐसा करना शुरू कर दिया। कुछ लोगों को आश्चर्य नहीं होता कि उन्हें समस्या क्यों है।

  2. इन वस्तुओं के बारे में सरल शब्दों में अपने शब्दों के सेट का विस्तार करें। यह कहना है, इन चीजों पर आपके द्वारा किए जा रहे विभिन्न गणनाओं को लिखें। 30 कुत्तों की आपकी छोटी सूची, 24 माप, 4 संपर्क, और कई "पैरामीटर" प्रति संपर्क दिलचस्प है, लेकिन कहानी का केवल एक हिस्सा है। आपका "प्रत्येक पंजा का स्थान" और "एक ही कुत्ते के सभी पंजे की तुलना यह निर्धारित करने के लिए कि संपर्क किस पंजा से है" ऑब्जेक्ट डिज़ाइन में अगला चरण है।

  3. संज्ञाओं को रेखांकित करें। गंभीरता से। कुछ लोग इसके मूल्य पर बहस करते हैं, लेकिन मुझे लगता है कि पहली बार OO डेवलपर्स के लिए यह मदद करता है। संज्ञाओं को रेखांकित करें।

  4. संज्ञाओं की समीक्षा करें। सामान्य पैरामीटर जैसे "पैरामीटर" और "माप" को विशिष्ट, ठोस संज्ञाओं के साथ बदलने की आवश्यकता है जो आपकी समस्या डोमेन में आपकी समस्या पर लागू होती हैं। विशेषण समस्या को स्पष्ट करने में मदद करते हैं। जेनरिक केवल विवरणों का वर्णन करते हैं।

  5. प्रत्येक संज्ञा के लिए ("संपर्क", "पंजा", "कुत्ता", आदि) उस संज्ञा की विशेषताओं और उन कार्यों को लिखते हैं जिनमें वह वस्तु संलग्न होती है। इसे शॉर्ट-कट न करें। हर विशेषता। उदाहरण के लिए "डेटा सेट में 30 कुत्ते होते हैं" महत्वपूर्ण है।

  6. प्रत्येक विशेषता के लिए, यह पहचानें कि क्या यह परिभाषित संज्ञा का संबंध है, या किसी अन्य प्रकार का "आदिम" या "परमाणु" डेटा जैसे कि एक स्ट्रिंग या फ्लोट या कुछ इर्रेड्यूबल है।

  7. प्रत्येक क्रिया या संचालन के लिए, आपको यह पहचानना होगा कि किस संज्ञा की जिम्मेदारी है, और कौन सी संज्ञाएं केवल भाग लेती हैं। यह "उत्परिवर्तन" का सवाल है। कुछ वस्तुओं को अद्यतन किया जाता है, अन्य नहीं। उत्परिवर्तित वस्तुओं को उनके उत्परिवर्तन के लिए कुल जिम्मेदारी होनी चाहिए।

  8. इस बिंदु पर, आप संज्ञाओं को वर्ग परिभाषाओं में बदलना शुरू कर सकते हैं। कुछ सामूहिक संज्ञाएं सूचियां, शब्दकोष, ट्यूपल्स, सेट या नामरूप हैं, और आपको बहुत अधिक काम करने की आवश्यकता नहीं है। अन्य कक्षाएं अधिक जटिल हैं, या तो जटिल व्युत्पन्न डेटा के कारण या कुछ अद्यतन / उत्परिवर्तन के कारण जो प्रदर्शन किया जाता है।

यूनिटेस्ट का उपयोग करके अलगाव में प्रत्येक वर्ग का परीक्षण करना न भूलें।

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


24

निम्नलिखित सलाह (@ S.Lott की सलाह के समान), पुस्तक की शुरुआत हैं , पायथन: नोविस से व्यावसायिक तक

  1. अपनी समस्या का वर्णन लिखें (समस्या क्या होनी चाहिए?)। सभी संज्ञा, क्रिया और विशेषण को रेखांकित करें।

  2. संज्ञाओं के माध्यम से जाओ, संभावित वर्गों की तलाश में।

  3. संभावित तरीकों की तलाश में, क्रियाओं के माध्यम से जाएं।

  4. संभावित विशेषताओं की तलाश में, विशेषणों के माध्यम से जाएं

  5. अपनी कक्षाओं के लिए तरीकों और विशेषताओं को आवंटित करें

कक्षा को परिष्कृत करने के लिए, पुस्तक यह भी सलाह देती है कि हम निम्नलिखित कार्य कर सकते हैं:

  1. नीचे लिखें (या सपना देखें) उपयोग के मामलों का एक सेट- कैसे आपके कार्यक्रम का उपयोग किया जा सकता है। सभी कार्यात्मक रूप से कवर करने का प्रयास करें।

  2. हर उपयोग केस स्टेप के माध्यम से सोचें, सुनिश्चित करें कि हमें जो कुछ भी चाहिए वह कवर किया गया है।


अच्छा होगा कि हम जिस तरह के वाक्य लिखने वाले हैं, उसके कुछ उदाहरण हों।

14

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

कभी-कभी, इस प्रारंभिक प्रक्रिया के दौरान, आपको एक ऐसा व्यवहार मिलेगा जो परीक्षण करने के लिए कठिन है और केवल परीक्षण करने के लिए विघटित होने की आवश्यकता है। यह एक संकेत हो सकता है कि एक अलग वर्ग वारंट किया गया है।

फिर मजेदार हिस्सा ... रिफलेक्टिंग। आपके पास काम करने वाले सॉफ़्टवेयर के बाद आप जटिल टुकड़े देख सकते हैं। नए वर्ग का सुझाव देते हुए अक्सर व्यवहार की थोड़ी जेब स्पष्ट हो जाएगी, लेकिन यदि नहीं, तो कोड को सरल बनाने के तरीकों की तलाश करें। सेवा ऑब्जेक्ट और मान ऑब्जेक्ट निकालें। अपनी विधियों को सरल बनाएं।

यदि आप सही तरीके से git का उपयोग कर रहे हैं (आप git का उपयोग कर रहे हैं, तो आप नहीं हैं?), आप बहुत जल्दी किसी विशेष अपघटन के साथ प्रयोग कर सकते हैं रिफैक्टरिंग के दौरान, और फिर इसे छोड़ दें और वापस लौटें यदि यह चीजों को सरल नहीं करता है।

पहले परीक्षण किए गए कार्य कोड को लिखकर आपको समस्या डोमेन में एक अंतरंग अंतर्दृष्टि प्राप्त करनी चाहिए जिसे आप आसानी से डिजाइन-प्रथम दृष्टिकोण के साथ प्राप्त नहीं कर सकते। लेखन परीक्षण और कोड आपको अतीत में धकेल देते हैं कि "मैं कहां से शुरू करता हूं" पक्षाघात।


1
मैं भी इस जवाब से सहमत हूं, हालांकि समस्या को तोड़ना और संभव वर्गों की पहचान करना (यानी "बस पर्याप्त" सॉफ्टवेयर आर्किटेक्चर करना) बहुत उपयोगी हो सकता है अगर समस्या टीम के कई सदस्यों द्वारा समानांतर में काम की जा रही है।
बेन स्मिथ

3

OO डिजाइन का पूरा विचार आपके कोड मैप को आपकी समस्या के रूप में बनाना है, इसलिए, उदाहरण के लिए, आप एक कुत्ते का पहला कदम चाहते हैं, आप कुछ ऐसा करते हैं:

dog.footstep(0)

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

 class Dog:
   def __init__(self):
     self._footsteps=None 
   def footstep(self,n):
     if not self._footsteps:
        self.readInFootsteps(...)
     return self._footsteps[n]

[यह अब एक प्रकार का कैशिंग पैटर्न है। पहली बार यह फ़ुटस्टेप डेटा को पढ़ता है और बाद में इसे स्वयं से प्राप्त करता है।

लेकिन हां, OO का डिजाइन सही होना मुश्किल हो सकता है। उन चीजों के बारे में अधिक सोचें जो आप अपने डेटा के लिए करना चाहते हैं, और यह सूचित करेगा कि आपको किन वर्गों के लिए आवेदन करने की आवश्यकता होगी।


2

अपनी संज्ञाओं, क्रियाओं, विशेषणों को लिखना एक महान दृष्टिकोण है, लेकिन मैं वर्ग डिजाइन के बारे में सोचना पसंद करता हूं क्योंकि यह सवाल पूछ रहा है कि क्या डेटा छिपाया जाना चाहिए ?

कल्पना कीजिए कि आपके पास एक Queryवस्तु और एक Databaseवस्तु थी:

Queryवस्तु आप बनाने में सहायता करते हैं और एक प्रश्न स्टोर करेगा - दुकान, कुंजी यहाँ, के रूप में एक समारोह की सहायता से आप एक बस के रूप में आसानी से बना है। शायद आप रह सकते हैं Query().select('Country').from_table('User').where('Country == "Brazil"'):। यह बिल्कुल वाक्यविन्यास से कोई फर्क नहीं पड़ता - यह आपका काम है! - कुंजी वह वस्तु है जो आपको कुछ छिपाने में मदद कर रही है , इस मामले में क्वेरी को स्टोर और आउटपुट करने के लिए आवश्यक डेटा। ऑब्जेक्ट की शक्ति इसका उपयोग करने के सिंटैक्स से आती है (इस मामले में कुछ चतुर जंजीर) और यह जानने की आवश्यकता नहीं है कि यह काम करने के लिए क्या स्टोर करता है। यदि सही किया जाता है तो Queryऑब्जेक्ट एक से अधिक डेटाबेस के लिए क्वेरी को आउटपुट कर सकता है। यह आंतरिक रूप से एक विशिष्ट प्रारूप को संग्रहीत करता है, लेकिन आउटपुट करते समय आसानी से अन्य प्रारूपों में परिवर्तित हो सकता है (पोस्टग्रेज, माईएसक्यूएल, मोंगबीडी)।

अब Databaseवस्तु के माध्यम से विचार करते हैं । यह क्या छुपाता है और संग्रहीत करता है? अच्छी तरह से स्पष्ट रूप से यह डेटाबेस की पूरी सामग्री को स्टोर नहीं कर सकता है, क्योंकि यही कारण है कि हमारे पास डेटाबेस है! तो फिर विषय बिंदु क्या है? लक्ष्य यह छिपाना है कि डेटाबेस उन लोगों से कैसे काम करता है जो Databaseऑब्जेक्ट का उपयोग करते हैं । आंतरिक राज्य में हेरफेर करने पर अच्छी कक्षाएं तर्क को सरल बनाएंगी। इस Databaseऑब्जेक्ट के लिए आप यह छिपा सकते हैं कि नेटवर्किंग कॉल कैसे काम करती है, या बैच क्वेरीज़ या अपडेट या कैशिंग लेयर प्रदान करती है।

समस्या यह है कि यह Databaseबहुत बड़ा है। यह दर्शाता है कि डेटाबेस का उपयोग कैसे किया जाता है, इसलिए कवर के तहत यह कुछ भी और सब कुछ कर सकता है। स्पष्ट रूप से नेटवर्किंग, कैशिंग, और बैचिंग आपके सिस्टम के आधार पर निपटने के लिए काफी कठिन हैं, इसलिए उन्हें छुपाना बहुत मददगार होगा। लेकिन, जैसा कि बहुत से लोग ध्यान देंगे, एक डेटाबेस पागलपन से जटिल है, और कच्चे डीबी कॉल से आगे आपको मिलता है, यह कठिन है कि प्रदर्शन के लिए ट्यून करें और समझें कि चीजें कैसे काम करती हैं।

यह ओओपी का मौलिक व्यापार है। यदि आप सही अमूर्त उठाते हैं, तो यह कोडिंग को सरल बनाता है (स्ट्रिंग, एरे, डिक्शनरी), यदि आप एक एब्सट्रैक्शन उठाते हैं जो बहुत बड़ा है (डेटाबेस, ईमेल मैनजर, ​​नेटवर्किंग मैन), तो यह वास्तव में समझने के लिए बहुत जटिल हो सकता है कि यह काम करता है, या क्या करना है उम्मीद करते हैं। लक्ष्य जटिलता को छिपाना है , लेकिन कुछ जटिलता आवश्यक है। अंगूठे का एक अच्छा नियम Managerवस्तुओं से बचने के लिए शुरू करना है, और इसके बजाय ऐसी कक्षाएं बनाएं जो इस तरह हैं structs- वे सभी डेटा पकड़ते हैं, कुछ सहायक विधियों के साथ आपके जीवन को आसान बनाने के लिए डेटा बनाने / हेरफेर करने के लिए। उदाहरण के लिए, EmailManagerएक फ़ंक्शन के साथ शुरुआत के मामले में कहा जाता है sendEmailजो एक Emailवस्तु लेता है। यह एक सरल प्रारंभिक बिंदु है और कोड को समझना बहुत आसान है।

अपने उदाहरण के लिए, इस बारे में सोचें कि आप जो खोज रहे हैं उसकी गणना करने के लिए किन डेटा की आवश्यकता है। यदि आप जानना चाहते हैं कि कोई जानवर कितनी दूर तक चल रहा था, उदाहरण के लिए, आपके पास ( AnimalStepऔर AnimalTripएनिमस्टेप्स का संग्रह) कक्षाएं हो सकती हैं। अब जब प्रत्येक Trip के पास सभी चरण डेटा हैं, तो उसे इसके बारे में सामान का पता लगाने में सक्षम होना चाहिए, शायद AnimalTrip.calculateDistance()समझ में आता है।


2

आपके लिंक किए गए कोड को स्किम करने के बाद, मुझे यह प्रतीत होता है कि आप इस बिंदु पर डॉग क्लास को डिज़ाइन नहीं कर रहे हैं । बल्कि, आपको पंडों और डेटाफ्रेम का उपयोग करना चाहिए । एक डेटाफ्रेम स्तंभों के साथ एक तालिका है। आप dataframe जैसे कॉलम होगा: dog_id, contact_part, contact_time, contact_location, आदि पांडा पर्दे के पीछे NumPy सरणी का उपयोग करता है, और यह आप के लिए कई सुविधा तरीकों है:

  • एक कुत्ते का चयन करें जैसे: my_measurements['dog_id']=='Charly'
  • जानकारी को बचाना: my_measurements.save('filename.pickle')
  • pandas.read_csv()पाठ फ़ाइलों को मैन्युअल रूप से पढ़ने के बजाय उपयोग करने पर विचार करें।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.