प्रश्न:__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) और *
-ऑपरेटर अनपॅकिंग का उपयोग करने का विकल्प है। तो मैं सोच रहा हूँ, क्या यह एक पूरी तरह से तटस्थ शैली का निर्णय है?
मैं तीन अलग-अलग तर्क स्वीकार करता हूं जो तब इस समस्या को कॉलर को ले जाते हैं - एक ट्यूपल, आखिरकार, तत्वों की एक निश्चित संख्या है। – user2246674