क्या यह एक कक्षा में विशेषताओं को प्रारंभिक-प्रारंभिक अभ्यास करना है, या उन्हें रास्ते में जोड़ना है?


11

मुझे खेद है कि अगर यह एक ABSOLUTELY सोफोमेरिक प्रश्न है, लेकिन मैं उत्सुक हूं कि सबसे अच्छे अभ्यास क्या हैं, और मुझे Google पर एक अच्छा जवाब नहीं मिल रहा है।

पायथन में, मैं आमतौर पर एक सुपर-कैटचेल डेटा संरचना कंटेनर (एक JSON फ़ाइल की तरह) के रूप में एक खाली वर्ग का उपयोग करता हूं, और रास्ते में विशेषताओं को जोड़ता हूं:

class DataObj:
    "Catch-all data object"
    def __init__(self):
        pass

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

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

हालांकि, हाल ही में यह मुझ पर (एफपी प्रोग्रामर्स द्वारा) प्रभावित हुआ है कि यह एक भयानक अभ्यास है, क्योंकि यह कोड को पढ़ने के लिए बहुत कठिन बनाता है। DataObj के पास वास्तव में क्या विशेषताएँ हैं, यह जानने के लिए सभी कोड से गुजरना पड़ता है।

प्रश्न : मैं लचीलेपन का त्याग किए बिना अधिक स्थिरता के लिए इसे कैसे लिख सकता हूं?

क्या कार्यात्मक प्रोग्रामिंग से कोई विचार है जिसे मैं अपना सकता हूं?

मैं वहाँ सर्वोत्तम प्रथाओं की तलाश कर रहा हूँ।

नोट : एक विचार वर्ग को उन सभी विशेषताओं के साथ प्रारंभिक-आरंभ करना है, जो किसी से मुठभेड़ की उम्मीद करती है, जैसे

class DataObj:
    "Catch-all data object"
    def __init__(self):
        data.a = 0
        data.b = ""
        data.c = []

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

क्या यह वास्तव में एक अच्छा विचार है? क्या होगा अगर मुझे नहीं पता कि मेरी विशेषताएँ एक प्राथमिकता क्या हैं?


आपकी डेटा संरचनाएं इतनी अधिक परिवर्तनशील हैं कि आप उनके रख-रखाव से चिंतित हैं। अपने प्रचुर खाली समय ™ में, अपरिवर्तनीय डेटा मॉडल के बारे में इस लेख को पढ़ने का प्रयास करें । यह आपके डेटा के कारण के तरीके को पूरी तरह से बदल सकता है।
9000

@ 9000 इस तरह का एक लेख पहले से ही आश्वस्त फिर से आश्वस्त करता है। मेरे लिए यह एक से अधिक की तरह क्यों लग रहा था (कानाफूसी की सूची वास्तव में आश्वस्त नहीं है जब तक आप ऐसा महसूस नहीं करते हैं कि आपको उन लोगों की आवश्यकता है)। मेरे लिए यह VB में किसी को भी इनवॉइस अपडेट करने से मना नहीं करता है कि उनके इनवॉइस ऑब्जेक्ट की नई प्रतियां बनाने के लिए लगातार समझ में आता है (भुगतान, नई इनवॉइस ऑब्जेक्ट जोड़ें; भाग, नया चालान ऑब्जेक्ट जोड़ें)।
पॉल

जवाबों:


10

मैं लचीलेपन का त्याग किए बिना अधिक स्थिरता के लिए इसे फिर से कैसे लिख सकता हूं?

तुम नहीं। लचीलापन ठीक है जो समस्या का कारण बनता है। यदि कहीं भी कोई कोड बदल सकता है तो किसी ऑब्जेक्ट में क्या विशेषता है, तो स्थिरता पहले से ही टुकड़ों में है। आदर्श रूप से, प्रत्येक वर्ग में उन विशेषताओं का एक समूह होता है जो __init__प्रत्येक उदाहरण के लिए और उसके बाद पत्थर में सेट होते हैं । हमेशा संभव या समझदार नहीं, लेकिन जब भी आपके पास इससे बचने के लिए वास्तव में अच्छे कारण नहीं होते हैं, तो यह मामला होना चाहिए ।

एक विचार है कि सभी विशेषताओं के साथ वर्ग को पूर्व-प्रारंभ करना है जो एक मुठभेड़ की अपेक्षा करता है

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

क्या होगा अगर मुझे नहीं पता कि मेरी विशेषताएँ एक प्राथमिकता क्या हैं?

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

यदि आप दोहरावदार कंटेनर कक्षाएं लिखने से डरते हैं: विवेकपूर्ण तरीके से मेटाप्रोग्रामिंग लागू करें, या उपयोग करें collections.namedtupleयदि आपको निर्माण के बाद सदस्यों को म्यूट करने की आवश्यकता नहीं है (आपका एफपी दोस्त प्रसन्न होंगे)।


7

आप हमेशा एलेक्स मार्टेली के बंच क्लास का उपयोग कर सकते हैं । आपके मामले में:

class DataObj:
    "Catch-all data object"
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

def processData(inputs):
    data = DataObj(a=1, b="sym", c=[2,5,2,1])

इस तरह, कम से कम यह पाठक के लिए स्पष्ट है कि डेटा केवल एक गूंगा डेटा स्टोर है और कोई भी तुरंत देख सकता है कि कौन से मान एक नाम से संग्रहीत हैं, क्योंकि यह सब एक पंक्ति में होता है।

और हां, इस तरह से चीजें करना वास्तव में एक अच्छा विचार है, कभी-कभी।


1

मैं संभवतः दूसरे दृष्टिकोण का उपयोग करूंगा, संभवतः Noneअवैध डेटा को इंगित करने के लिए उपयोग करना। यह सच है कि यदि आप विशेषताओं को बाद में जोड़ते हैं, तो इसे पढ़ना / बनाए रखना मुश्किल है। हालाँकि, इस वर्ग / वस्तु के उद्देश्य के बारे में अधिक जानकारी इस बात की जानकारी देती है कि पहला विचार एक ख़राब डिज़ाइन क्यों है: आपके पास कभी पूरी तरह से खाली वर्ग होगा जिसमें कोई विधियाँ या डिफ़ॉल्ट डेटा नहीं होगा? आपको यह क्यों नहीं पता होगा कि कक्षा में क्या विशेषताएं हैं?

यह संभव है कि processDataएक विधि के रूप में बेहतर हो सकता है ( process_dataअजगर नामकरण सम्मेलनों का पालन करने के लिए), क्योंकि यह कक्षा पर कार्य करता है। उदाहरण को देखते हुए, ऐसा लगता है कि यह डेटा संरचना (जहां dictपर्याप्त हो सकता है) के रूप में बेहतर हो सकता है ।

एक वास्तविक उदाहरण को देखते हुए, आप प्रश्न को CodeReview में ले जाने पर विचार कर सकते हैं, जहाँ वे कोड को फिर से भरने में मदद कर सकते हैं।

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