2012-10-25 6 views
19

मैं ज्यादातर पाइथन के बारे में बात कर रहा हूं, लेकिन मुझे लगता है कि यह शायद अधिकतर भाषाओं के लिए है। अगर मेरे पास एक म्यूटेबल ऑब्जेक्ट है, तो क्या इन-प्लेस ऑपरेशन को ऑब्जेक्ट वापस करने का बुरा विचार है? ऐसा लगता है कि अधिकांश उदाहरण बस ऑब्जेक्ट को संशोधित करते हैं और None लौटाते हैं। उदाहरण के लिए, list.sortइन-प्लेस ऑपरेशंस बनाना ऑब्जेक्ट को एक बुरा विचार वापस कर रहा है?

+0

मुझे लगता है कि यह स्थिरता के बारे में सब कुछ है। पाइथन इन-प्लेस ऑपरेशंस होने पर परिवर्तनीय वस्तुओं पर विधियों के बारे में काफी संगत है। जब तक आप इसके बारे में संगत होते हैं, तब तक किसी ऑब्जेक्ट या ऑब्जेक्ट संदर्भ को वापस करने वाले इन-प्लेस ऑपरेशंस के साथ कोई समस्या नहीं होनी चाहिए। –

+0

लेकिन यह पहली जगह क्यों है? – asmeurer

+2

मैं 100% निश्चित नहीं हूं, लेकिन अधिकांश समय, ऑब्जेक्ट को वापस करने के लिए इन-प्लेस ऑपरेशन की आवश्यकता नहीं होती है। आप एक नई वस्तु नहीं बना रहे हैं जिसे आवंटित करने की आवश्यकता है। इसके अतिरिक्त, इस तथ्य को बनाने के लिए प्रत्येक इन-प्लेस ऑपरेशन के अनुरूप हैं कि आप कुछ और संचालन स्पष्ट रूप से स्पष्ट करने के लिए कुछ कर रहे हैं। (उदाहरण के लिए 'list.sort' बनाम' क्रमबद्ध (सूची) ', 'list.reverse' बनाम' उल्टा (सूची)') –

उत्तर

25

हां, यह एक बुरा विचार है। इसका कारण यह है कि यदि जगह और गैर-जगह वाले संचालन स्पष्ट रूप से समान आउटपुट होते हैं, तो प्रोग्रामर अक्सर इन-प्लेस ऑपरेशंस और गैर-इन-प्लेस ऑपरेशंस (List.sort() बनाम sorted()) को मिश्रित करेंगे और इसके परिणामस्वरूप हार्ड-टू त्रुटियों की पहचान करें।

इन-प्लेस ऑपरेशंस स्वयं को लौटने से आपको "विधि श्रृंखला" करने की अनुमति मिल सकती है, हालांकि, यह खराब अभ्यास है क्योंकि आप दुर्घटना से श्रृंखला के बीच में दुष्प्रभावों के साथ कार्यों को दफन कर सकते हैं।

इस तरह की त्रुटियों को रोकने के लिए, विधि श्रृंखलाओं में केवल साइड-इफेक्ट्स के साथ एक विधि होनी चाहिए, और यह फ़ंक्शन श्रृंखला के अंत में होना चाहिए। श्रृंखला में इससे पहले के कार्यों को साइड इफेक्ट्स के बिना इनपुट को बदलना चाहिए (उदाहरण के लिए, एक पेड़ को नेविगेट करना, स्ट्रिंग को स्लाइस करना आदि)। यदि इन-प्लेस ऑपरेशंस स्वयं लौटते हैं तो एक प्रोग्रामर वैकल्पिक रूप से वैकल्पिक फ़ंक्शन के स्थान पर इसका उपयोग करने के लिए बाध्य होता है जो एक प्रतिलिपि देता है और इसलिए इसका कोई दुष्प्रभाव नहीं होता है (फिर, List.sort() बनाम sorted()) जिसके परिणामस्वरूप एक त्रुटि हो सकती है डिबग।

यही वजह है कि पायथन मानक लाइब्रेरी फ़ंक्शंस हमेशा एक प्रतिलिपि लौटाते हैं या None लौटाते हैं और ऑब्जेक्ट्स को जगह में संशोधित करते हैं, लेकिन ऑब्जेक्ट्स को कभी भी संशोधित नहीं करते हैं और खुद को वापस भी नहीं करते हैं। Django जैसे अन्य पायथन पुस्तकालय भी इस अभ्यास का पालन करते हैं (Django के बारे में this very similar question देखें)।

+0

एक सामान्य नियम के रूप में सहमत है, लेकिन मुझे लगता है कि कुछ विशिष्ट मामलों में अपवाद हैं, जो बहुत दुर्लभ नहीं हैं। Eg1: जब विधि का अर्थात् स्पष्ट रूप से एक जगह ऑपरेशन है, जैसे कि jQuery की '.empty() '। Eg2: जब एपीआई का उपयोग आमतौर पर किया जाता है कि हर कोई इसे पहली बार शुरू करने से जानता है और इसमें कोई संस्करण नहीं है जो एक प्रतिलिपि है, जैसे jQuery की '.append() ' –

+0

बस क्योंकि विधि का नाम वर्तमान काल क्रिया है, नहीं इसका मतलब है कि लोगों को यह स्पष्ट लगेगा कि ऑपरेशन जगह-जगह पर कार्य करता है। पाइथन सीखने के बाद मुझे काफी समय लगा जब मुझे हमेशा याद आया कि 'list.sort' ने जगह बनाई है, भले ही नाम ऐसा लगता है कि ऐसा करना चाहिए। – asmeurer

+0

क्या अभी भी एक जगह के संचालन के साथ एक श्रृंखला समाप्त करने के साथ भ्रम नहीं है? 'a.sort()' और 'a [: 2] .sort()' पूरी तरह से अलग-अलग चीजें करने जा रहे हैं (मुझे लगता है कि अगर आप किसी numpy 'array' जैसे कुछ उपयोग करते हैं, तो यह अलग होगा)। शायद मुद्दा यह है कि 'कोई भी' वापस लौटने वाला 'कोई नहीं' आपको यह सोचने से बचाता है कि 'a [: 2] .sort()' कुछ भी उपयोगी है? – asmeurer

0

मुझे लगता है कि यह उपयोग के मामले पर निर्भर करता है। मैं नहीं देखता कि इन-प्लेस ऑपरेशन से किसी ऑब्जेक्ट को वापस क्यों करना होगा, इसके अलावा आप परिणाम का उपयोग नहीं करेंगे, लेकिन यह वास्तव में कोई समस्या नहीं है यदि आप शुद्ध कार्यात्मकता के बारे में अति-भरोसेमंद नहीं हैं। मुझे कॉल-चेनिंग पैटर्न पसंद है, जैसे कि jQuery का उपयोग करता है, इसलिए जब मैं इसे और अधिक उपयोग करना चाहता हूं तो फ़ंक्शन उस ऑब्जेक्ट को वापस लौटाता है जब मैं कार्य करता हूं।

8

संशोधित ऑब्जेक्ट को संशोधित करने वाली विधि से लौटने से इसमें कुछ लाभ हो सकते हैं, लेकिन पाइथन में इसकी अनुशंसा नहीं की जाती है। एक संशोधन ऑपरेशन के बाद self लौटने से आप ऑब्जेक्ट पर method chaining निष्पादित करने की अनुमति देंगे, जो एक ही ऑब्जेक्ट पर कई विधियों को निष्पादित करने का एक सुविधाजनक तरीका है, यह ऑब्जेक्ट उन्मुख प्रोग्रामिंग में एक बहुत ही सामान्य मुहावरे है। और बदले में, विधि चेनिंग fluent interfaces के सीधा कार्यान्वयन की अनुमति देता है। इसके अलावा, यह कुछ कार्यात्मक-प्रोग्रामिंग मुहावरे को अधिक आसानी से व्यक्त करने की अनुमति देता है।

कुछ उदाहरणों का नाम देने के लिए: पायथन में, Moka लाइब्रेरी विधि श्रृंखला का उपयोग करता है। जावा में, StringBuilder वर्ग एक ही ऑब्जेक्ट पर एकाधिक append() आमंत्रणों की अनुमति देता है। जावास्क्रिप्ट में, JQuery बड़े पैमाने पर विधि का उपयोग करता है। स्मॉलटाक इस विचार को अगले स्तर पर ले जाता है: डिफ़ॉल्ट रूप से, सभी विधियां self वापस लौटाती हैं जब तक कि अन्यथा निर्दिष्ट नहीं किया जाता है (इसलिए विधि को संयोजित करने के लिए प्रोत्साहित किया जाता है) - यह पाइथन के साथ विपरीत है, जो डिफ़ॉल्ट रूप से None देता है।

पायथन में इस मुहावरे का उपयोग सामान्य नहीं है, क्योंकि पाइथन Command/Query Separation Principle का पालन करता है, जिसमें कहा गया है कि "प्रत्येक विधि या तो एक आदेश होनी चाहिए, या एक क्वेरी जो कॉलर को डेटा लौटाती है, लेकिन नहीं दोनों "।

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

+1

उत्कृष्ट उत्तर के लिए धन्यवाद, विशेष रूप से कमांड/क्वेरी सेपरेशन सिद्धांत के लिंक, जो मदद करता है मैं हाल ही में कुछ डिजाइन व्यापार-बंद करने के लिए एक लेबल संलग्न करता हूं। – FMc

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