पायथन के ज़ेन का कहना है कि चीजों को करने का केवल एक ही तरीका होना चाहिए- फिर भी अक्सर मैं यह तय करने की समस्या में दौड़ता हूं कि किसी फ़ंक्शन का उपयोग कब करें और कब एक विधि का उपयोग करें।
आइए एक तुच्छ उदाहरण लेते हैं- एक शतरंज बोर्ड वस्तु। मान लीजिए कि हमें बोर्ड पर उपलब्ध सभी कानूनी चालों को प्राप्त करने के लिए किसी तरह की आवश्यकता है। क्या हम ChessBoard.get_king_moves () या get_king_moves (chess_board) लिखते हैं?
यहाँ कुछ संबंधित प्रश्न हैं जिन्हें मैंने देखा:
- अजगर 'जादू विधियों' का उपयोग क्यों करता है?
- क्या कोई कारण है कि पायथन स्ट्रिंग्स में एक स्ट्रिंग लंबाई विधि नहीं है?
मुझे जो उत्तर मिले वे काफी हद तक अनिर्णायक थे:
पायथन कुछ कार्यक्षमता के लिए तरीकों का उपयोग क्यों करता है (जैसे सूची.इंडेक्स ()) लेकिन अन्य के लिए कार्य करता है (जैसे लेन (सूची))?
इसकी बड़ी वजह इतिहास है। उन कार्यों के लिए फ़ंक्शंस का उपयोग किया गया था जो प्रकार के समूह के लिए सामान्य थे और जिनका उद्देश्य उन वस्तुओं के लिए भी काम करना था जिनके पास बिल्कुल भी तरीके नहीं थे (उदाहरण के लिए ट्यूल)। जब आप पायथन के कार्यात्मक सुविधाओं का उपयोग करते हैं (मानचित्र) (लागू), (एट)।
वास्तव में, अंतर्निहित फ़ंक्शन के रूप में लेन (), अधिकतम (), मिनट () को लागू करना वास्तव में प्रत्येक प्रकार के तरीकों के रूप में उन्हें लागू करने की तुलना में कम कोड है। कोई व्यक्ति व्यक्तिगत मामलों के बारे में विचार कर सकता है, लेकिन यह पायथन का एक हिस्सा है, और अब इस तरह के मूलभूत परिवर्तन करने में बहुत देर हो चुकी है। बड़े पैमाने पर कोड टूटने से बचने के लिए कार्यों को करना पड़ता है।
जबकि दिलचस्प है, ऊपर वास्तव में क्या रणनीति को अपनाने के लिए के रूप में ज्यादा नहीं कहता है।
यह एक कारण है - कस्टम तरीकों के साथ, डेवलपर्स एक अलग विधि का नाम चुनने के लिए स्वतंत्र होंगे, जैसे कि गेटलॉन्ग (), लंबाई (), गेटलिफ्ट () या जो भी हो। पायथन सख्त नामकरण को लागू करता है ताकि आम फ़ंक्शन लेन () का उपयोग किया जा सके।
थोड़ा और दिलचस्प। मेरा लेना यह है कि कार्य एक अर्थ में हैं, इंटरफेस का पायथन संस्करण।
अंत में, स्वयं Guido से :
क्षमताओं / इंटरफेस के बारे में बात करते हुए मुझे हमारे "दुष्ट" विशेष विधि नामों में से कुछ के बारे में सोचते हैं। भाषा के संदर्भ में, यह कहता है, "एक वर्ग कुछ विशेष कार्यों को लागू कर सकता है जो विशेष सिंटैक्स (जैसे अंकगणितीय संचालन या सबस्क्रिप्टिंग और स्लाइसिंग) द्वारा लागू किए जाते हैं, विशेष नामों के साथ तरीकों को परिभाषित करके।" लेकिन इन सभी विधियों में विशेष नाम हैं जैसे कि
__len__
या__unicode__
जो सिंटैक्स के समर्थन के बजाय अंतर्निहित कार्यों के लाभ के लिए प्रदान किए गए प्रतीत होते हैं। संभवतः एक इंटरफ़ेस-आधारित पायथन में, ये विधियां एबीसी पर नियमित रूप से नामित विधियों में बदल जाएंगी, इसलिए यह__len__
बन जाएगीclass container: ... def len(self): raise NotImplemented
हालाँकि, इसके बारे में कुछ और सोचने के कारण, मैं यह नहीं देखता कि सभी सिंथैटिक ऑपरेशन किसी विशिष्ट ABC पर उपयुक्त सामान्य रूप से नामित विधि को
<
object.lessthan
comparable.lessthan
क्यों लागू नहीं करेंगे। " ", उदाहरण के लिए, संभवतः " " या (शायद " ") को लागू करेगा । तो एक और लाभ इस आम-नाम की विषमता से दूर अजगर को दूर करने की क्षमता होगी, जो मुझे एक एचसीआई सुधार लगता है ।हम्म। मुझे यकीन नहीं है कि मैं सहमत हूं (यह आंकड़ा :-)
"पायथन औचित्य" के दो टुकड़े हैं जिन्हें मैं पहले समझाना चाहता हूँ।
सबसे पहले, मैंने HCI कारणों के लिए x.len () पर लेन (x) चुना (
def __len__()
बहुत बाद में आया)। वास्तव में दो अलग-अलग कारण हैं, दोनों HCI:(ए) कुछ संचालन के लिए, उपसर्ग संकेतन सिर्फ उपसर्ग की तुलना में बेहतर पढ़ता है - उपसर्ग (और infix!) संचालन की गणित में एक लंबी परंपरा है जो उन धारणाओं को पसंद करते हैं जहां दृश्य किसी समस्या के बारे में गणितज्ञ की सोच में मदद करते हैं। आसान, जिनके साथ हम की तरह एक सूत्र को फिर से लिखने की तुलना
x*(a+b)
मेंx*a + x*b
एक कच्चे OO अंकन का उपयोग ही बात कर के भद्दापन है।(b) जब मैं कोड पढ़ता हूं जो कहता है कि
len(x)
मुझे पता है कि यह किसी चीज की लंबाई पूछ रहा है। यह मुझे दो बातें बताता है: परिणाम एक पूर्णांक है, और तर्क कुछ प्रकार के कंटेनर है। इसके विपरीत, जब मैं पढ़ता हूं, तो मुझेx.len()
पहले से ही पता होताx
है कि किसी प्रकार का कंटेनर एक इंटरफ़ेस को लागू कर रहा है या एक मानक से विरासत में मिला हैlen()
। भ्रम की गवाह हमारे पास कभी-कभार होती है जब एक वर्ग जो मैपिंग को लागू नहीं कर रहा होता है उसके पास एक विधिget()
याkeys()
विधि होती है, या ऐसी कोई चीज़ जो किसी फ़ाइल में नहींwrite()
होती है।एक ही बात को दूसरे तरीके से कहते हुए, मैं 'लेन' को एक अंतर्निहित ऑपरेशन के रूप में देखता हूं । मुझे लगता है कि खोने के लिए नफरत करता हूँ। मैं यह सुनिश्चित करने के लिए नहीं कह सकता कि आपका मतलब है या नहीं, लेकिन 'डीईएन लेन (सेल्फ): ...' निश्चित रूप से लगता है कि आप इसे एक साधारण विधि के लिए आवंटित करना चाहते हैं। मैं दृढ़ता से उस पर -1 हूँ।
पायथन औचित्य का दूसरा बिट मैंने समझाने का वादा किया है यही कारण है कि मैंने
__special__
केवल देखने के लिए विशेष तरीकों को चुना और केवल नहींspecial
। मैं बहुत सारे ऑपरेशनों का अनुमान लगा रहा था कि कक्षाएं ओवरराइड करना चाह सकती हैं, कुछ मानक (जैसे__add__
या__getitem__
), कुछ मानक नहीं हैं (उदाहरण के__reduce__
लिए अचार लंबे समय तक सी कोड में कोई समर्थन नहीं था)। मैं नहीं चाहता था कि ये विशेष ऑपरेशन साधारण विधि के नाम का उपयोग करें, क्योंकि तब पहले से मौजूद कक्षाएं, या सभी विशेष विधियों के लिए विश्वकोश मेमोरी के बिना उपयोगकर्ताओं द्वारा लिखी गई कक्षाएं, गलती से उन कार्यों को परिभाषित करने के लिए उत्तरदायी होंगी, जिन्हें लागू करने के लिए उनका कोई मतलब नहीं था। , संभवतः विनाशकारी परिणामों के साथ। इवान क्रस्टिएक ने अपने संदेश में इसे और अधिक स्पष्ट किया, जो कि मैंने यह सब लिखने के बाद किया था।- - ग्यूडो वैन रोसुम (होम पेज: http://www.python.org/~guido/ )
इस बारे में मेरी समझ यह है कि कुछ मामलों में, उपसर्ग संकेतन सिर्फ अधिक अर्थ बनाता है (यानी, डक। मैक एक भाषाई दृष्टिकोण से क्वैक (डक) की तुलना में अधिक समझ में आता है।) और फिर, फ़ंक्शन "इंटरफेस" की अनुमति देते हैं।
ऐसी स्थिति में, मेरा अनुमान केवल Guido के पहले बिंदु पर आधारित get_king_moves को लागू करना होगा। लेकिन फिर भी यह कहना है कि एक समान धक्का और पॉप तरीकों के साथ एक ढेर और कतार वर्ग को लागू करने के बारे में बहुत सारे खुले प्रश्न हैं - क्या वे कार्य या विधियां होनी चाहिए? (यहां मैं कार्यों का अनुमान लगाऊंगा, क्योंकि मैं वास्तव में एक पुश-पॉप इंटरफ़ेस को संकेत देना चाहता हूं)
TLDR: क्या कोई समझा सकता है कि कार्यों बनाम विधियों का उपयोग करते समय निर्णय लेने की रणनीति क्या होनी चाहिए?
X.frob
याX.__frob__
स्वतंत्र है या नहींfrob
।