2013-06-20 9 views
8

प्रश्न:__init__ लिखने के पेशेवरों और विपक्ष क्या हैं जो इसकी सामग्री को अनपॅक करने के बजाय सीधे एक तर्क के रूप में संग्रह लेते हैं?अपनी सामग्री को अनपॅक किए बिना संग्रह तर्क पास करना

संदर्भ: मैं डेटाबेस तालिका में कई फ़ील्ड से डेटा को संसाधित करने के लिए एक कक्षा लिख ​​रहा हूं। मैं कुछ बड़े (~ 100 मिलियन पंक्तियों) क्वेरी परिणाम के माध्यम से पुनरावृत्ति करता हूं, एक समय में एक पंक्ति को एक वर्ग में पास करता हूं जो प्रसंस्करण करता है। प्रत्येक पंक्ति डेटाबेस से एक tuple (या वैकल्पिक रूप से, एक शब्दकोश के रूप में) के रूप में पुनर्प्राप्त किया जाता है।

चर्चा: मान लीजिए कि मुझे बिल्कुल तीन क्षेत्रों में दिलचस्पी है, लेकिन मेरी कक्षा में जो भी हो जाता है वह क्वेरी पर निर्भर करता है, और क्वेरी उपयोगकर्ता द्वारा लिखी जाती है। सबसे बुनियादी दृष्टिकोण निम्न में से एक हो सकता है:

class Direct: 
    def __init__(self, names): 
     self.names = names 

class Simple: 
    def __init__(self, names): 
     self.name1 = names[0] 
     self.name2 = names[1] 
     self.name3 = names[2] 

class Unpack: 
    def __init__(self, names): 
     self.name1, self.name2, self.name3 = names 

यहाँ कि एक नया उदाहरण के लिए पारित किया जा सकता है पंक्तियों के कुछ उदाहरण हैं:

good = ('Simon', 'Marie', 'Kent')     # Exactly what we want 
bad1 = ('Simon', 'Marie', 'Kent', '10 Main St') # Extra field(s) behind 
bad2 = ('15', 'Simon', 'Marie', 'Kent')   # Extra field(s) in front 
bad3 = ('Simon', 'Marie')       # Forgot a field 

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

Simple सही ढंग से bad1 संभालती है, जब bad2 दिया गाड़ी है, और जब bad3 दिया एक त्रुटि फेंकता है। bad1 से इनपुट को प्रभावी रूप से कम करने में सक्षम होना सुविधाजनक है, लेकिन bad2 से आने वाली बगों के लायक नहीं है। यह एक बेवकूफ और असंगत लगता है।

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

दूसरी ओर, संग्रह क्यों पास करते हैं? के बाद से मैं जानता हूँ कि मैं हमेशा तीन क्षेत्रों चाहता हूँ, मुझे __init__ परिभाषित स्पष्ट रूप से तीन तर्कों को स्वीकार कर सकते हैं, और * -operator का उपयोग कर संग्रह खोल के रूप में मैं नई वस्तु को इसे पारित: अंतर केवल मैं देख रहा हूँ रहे हैं

class Explicit: 
    def __init__(self, name1, name2, name3): 
     self.name1 = name1 
     self.name2 = name2 
     self.name3 = name3 

names = ('Guy', 'Rose', 'Deb') 
e = Explicit(*names) 

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

यदि मैं हमेशा तीनों की बजाय अनिश्चित संख्या में फ़ील्ड स्वीकार करना चाहता हूं, तो मुझे अभी भी सीधे ट्यूपल पास करने या मनमानी तर्क सूचियों (* तर्क, ** kwargs) और *-ऑपरेटर अनपॅकिंग का उपयोग करने का विकल्प है। तो मैं सोच रहा हूँ, क्या यह एक पूरी तरह से तटस्थ शैली का निर्णय है?

+1

मैं तीन अलग-अलग तर्क स्वीकार करता हूं जो तब इस समस्या को कॉलर को ले जाते हैं - एक ट्यूपल, आखिरकार, तत्वों की एक निश्चित संख्या है। – user2246674

उत्तर

6

यह प्रश्न संभवतः विभिन्न दृष्टिकोणों को आजमाकर और को सबसे अधिक समझ में आता है और यह आपके कोड को पढ़ने वाले लोगों द्वारा सबसे अधिक आसानी से समझा जाता है।

अब मुझे और अनुभव का लाभ है, मैं खुद से पूछूंगा, मैं इन मूल्यों तक पहुंचने की योजना कैसे बना सकता हूं?

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

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

शेष शेष दृष्टिकोणों में संग्रह को अलग-अलग विशेषताओं में विभाजित करना शामिल है, और मुझे लगता है कि स्पष्ट विजेता यहां "स्पष्ट" दृष्टिकोण है। "सरल" और "अनपैक" दृष्टिकोण संग्रह के क्रम पर एक छिपी निर्भरता साझा करते हैं, बिना किसी वास्तविक लाभ के।

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