2009-10-12 27 views
11

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

क्या यह पाइथन पर भी लागू होता है? क्या आप अजगर में ऑपरेटर व्यवहार को ओवरराइड करने की सलाह देंगे? और अंगूठे के नियम क्या आप मुझे दे सकते हैं?

उत्तर

23

ऑपरेटर ओवरलोडिंग ज्यादातर उपयोगी है जब आप एक नया वर्ग है कि एक मौजूदा "सार बेस कक्षा" (एबीसी) में गिर जाता है बना रहे हैं में इस सिंटैक्स का उपयोग करता पाया - वास्तव में, मानक लाइब्रेरी मॉड्यूल collections में कई एबीसी कुछ विशेष तरीकों (और विशेष विधियों, डबल अंडरस्कोर एकेए "डंडर्स" के साथ शुरू होने और समाप्त होने वाले नामों के साथ भरोसा करते हैं, ठीक उसी तरह हैं जो आप पाइथन में ऑपरेटर ओवरलोडिंग करते हैं)। यह अच्छा प्रारंभिक मार्गदर्शन प्रदान करता है।

उदाहरण के लिए, एक Container वर्ग चाहिए विशेष विधि __contains__, ओवरराइड यानी, सदस्यता जांच ऑपरेटर item in container (के रूप में, if item in container: - for बयान, for item in container:, जो __iter__ पर निर्भर करता है के साथ भ्रमित न करें -) । इसी तरह, एक Hashable__hash__ ओवरराइड चाहिए, एक Sized__len__, एक Sequence ओवरराइड होनी चाहिए या उन्हें Mapping इसके आगे __getitem__ ओवरराइड, और चाहिए। (इसके अलावा, एबीसी आपकी कक्षा को मल्टीन कार्यक्षमता के साथ प्रदान कर सकता है - उदाहरण के लिए, Sequence और Mapping दोनों __contains__ प्रदान किए जा सकते हैं __getitem__ ओवरराइड के आधार पर, और इस प्रकार स्वचालित रूप से आपकी कक्षा को Container) बनाते हैं।

collections से परे, आप विशेष तरीकों को ओवरराइड करना चाहते हैं (यानी ऑपरेटर ओवरलोडिंग के लिए प्रदान करते हैं) अधिकतर यदि आपकी नई कक्षा "एक संख्या है"। अन्य विशेष मामले मौजूद हैं, लेकिन "सामान्य" अर्थों के लिए कोई अर्थपूर्ण कनेक्शन नहीं होने के कारण, "सामान्य" अर्थों के लिए कोई अर्थपूर्ण कनेक्शन नहीं है, क्योंकि सी ++ की धारा << और >> और पायथन स्ट्रिंग्स (पायथन 2.* में, सौभाग्य से 3.* में नहीं) अधिक ;-) % के लिए करें - जब ऐसे ऑपरेटरों का कोई और अर्थ "बिट-स्थानांतरण" या "विभाजन शेष" नहीं होता है, तो आप केवल उलझन में उलझन में हैं। एक भाषा की मानक लाइब्रेरी इससे दूर हो सकती है (हालांकि यह नहीं होना चाहिए ;-), लेकिन जब तक आपकी लाइब्रेरी भाषा के मानक के रूप में व्यापक नहीं हो जाती है, तो भ्रम की चोट होगी! -)

+4

बीटीडब्ल्यू से नापसंद करता है, उन लोगों के लिए निराशाजनक स्ट्रिंग स्वरूपण के लिए% नहीं होने का विचार: यद्यपि पायथन 3 दस्तावेज अप्रचलित के रूप में% का वर्णन करता है, फिर भी यह दस्तावेज है और ऐसा कोई मौका नहीं है कि फीथन 4 में पाइथन-देव में हालिया चर्चाओं के आधार पर यह सुविधा वास्तव में दूर जाएगी। यह 2.6 में पहले से उपलब्ध नई स्ट्रिंग प्रारूप विधि को सीखने और प्यार करने के लिए काफी समय देता है। –

+0

प्रारूप फ़ंक्शन% से कहीं अधिक बेहतर है – Casebash

12

मैंने अत्यधिक मात्रा में ओवरलोडिंग के साथ सॉफ्टवेयर लिखा है, और हाल ही में मुझे उस नीति पर खेद है। मैं यह कहूंगा:

केवल ओवरलोड ऑपरेटर अगर यह प्राकृतिक, अपेक्षित चीज है और इसका कोई दुष्प्रभाव नहीं है।

तो अगर आप एक नया RomanNumeral वर्ग बनाने के लिए, यह समझ में आता है ओवरलोड जोड़ और घटाव आदि लेकिन यह ओवरलोड नहीं है जब तक कि यह स्वाभाविक है: यह कोई मतलब नहीं है एक Car या एक Vehicle वस्तु के लिए जोड़ और घटाव परिभाषित करने के लिए ।

अंगूठे का एक और नियम: == अधिभारित न करें। यह वास्तव में परीक्षण करने के लिए बहुत कठिन बनाता है (हालांकि असंभव नहीं है) यदि दो ऑब्जेक्ट समान हैं। मैंने यह गलती की और इसके लिए लंबे समय तक भुगतान किया।

+=, ++ आदि को अधिभारित करने के लिए, मैं वास्तव में कहूंगा: केवल उस ऑपरेटर के लिए बहुत अधिक मांग होने पर अतिरिक्त ऑपरेटरों को ओवरलोड करें। पांच से कुछ करने का एक तरीका होना आसान है। निश्चित रूप से, इसका मतलब है कि कभी-कभी आपको x += 1 के बजाय x = x + 1 लिखना होगा, लेकिन अगर यह स्पष्ट है तो अधिक कोड ठीक है।

सामान्य रूप से, कई 'फैंसी' सुविधाओं के साथ, यह सोचना आसान है कि आप वास्तव में कुछ नहीं चाहते हैं, सामानों का एक समूह लागू करें, साइड इफेक्ट्स को नोटिस न करें, और उसके बाद इसे बाद में समझें। रूढ़िवादी पक्ष पर एरर।

संपादित करें: मैं == ओवरलोडिंग के बारे में एक स्पष्टीकरण नोट जोड़ना चाहता था, क्योंकि ऐसा लगता है कि विभिन्न टिप्पणीकर्ता इसे गलत समझते हैं, और यह मुझे पकड़ा गया है। हां, is मौजूद है, लेकिन यह एक अलग ऑपरेशन है। मान लें कि मेरे पास ऑब्जेक्ट x है, जो या तो मेरी कस्टम क्लास से है, या एक पूर्णांक है। मैं देखना चाहता हूं कि x संख्या 500 है। लेकिन यदि आप x = 500 सेट करते हैं, तो बाद में x is 500 का परीक्षण करें, आपको False मिलेगा, जिस तरह से पाइथन कैश संख्याएं होती हैं। 50 के साथ, यह True वापस करेगा। लेकिन आप is का उपयोग नहीं कर सकते हैं, क्योंकि True लौटने के लिए x == 500 वापस x आपकी कक्षा का एक उदाहरण है। भ्रामक? निश्चित रूप से। लेकिन ऑपरेटरों को सफलतापूर्वक अधिभारित करने के लिए आपको यह समझने की आवश्यकता है।

+2

ओवरलोडिंग '++' नहीं विशेष रूप से लागू होते हैं, क्योंकि पाइथन में '++' ऑपरेटर नहीं होता है। –

+0

यकीन है, मैं पायथन के लिए उदाहरण बदल दूंगा। (हालांकि मैं सामान्य सिद्धांत की व्याख्या करना चाहता था)। – Peter

+2

क्या आप परीक्षण नहीं कर सकते हैं कि यदि दो वस्तुएं हैं, तो 'if a b: ...' है, भले ही '==' अधिभारित हो?या क्या मैं उस बिंदु को गलत समझ रहा हूं जिसे आप बना रहे हैं? – sth

3

पायथन का अधिभार सी ++ के मुकाबले सामान्य रूप से "सुरक्षित" है - उदाहरण के लिए, असाइनमेंट ऑपरेटर को ओवरलोड नहीं किया जा सकता है, और += में एक समझदार डिफ़ॉल्ट कार्यान्वयन है।

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

आधुनिक पायथन शैली दृढ़ता से "दुष्ट" अधिभार को हतोत्साहित करती है, लेकिन भाषा और मानक पुस्तकालय के कई पहलुओं को पीछे की संगतता के लिए खराब नामित ऑपरेटरों को बनाए रखा जाता है।

  • %: मापांक और स्ट्रिंग
  • + स्वरूपण: इसके अलावा और अनुक्रम संयोजन
  • *: गुणा और अनुक्रम पुनरावृत्ति

तो, अंगूठे का नियम उदाहरण के लिए? यदि आपका ऑपरेटर कार्यान्वयन लोगों को आश्चर्यचकित करेगा, तो ऐसा न करें।

+0

मुझे लगता है कि '+' और '*' के दोहरे उपयोग योग्य हैं - दोनों कम से कम एक ही वैचारिक बात करते हैं, यहां तक ​​कि अगर वे इसे अलग करते हैं। –

+1

वे बिल्कुल समान नहीं हैं। '(1 + 2) == (2 + 1)', लेकिन '(" एक "+" बी ")! = (" बी "+" ए ")'। '(1 + 2-1) == 2', लेकिन' ("एक" + "बी" - "ए") बकवास है। गुणा के लिए एक ही तरह के मुद्दे मौजूद हैं। –

+3

मेरा मतलब यह नहीं था कि वे वही थे, लेकिन मैंने बुरी तरह से शब्द किया। मेरा मतलब था कि अवधारणात्मक रूप से वे समान कार्य करते हैं। मुझे लगता है कि ज्यादातर लोग कहेंगे कि दो तारों में शामिल होना और दो जोड़ों को "योजक" संचालन के रूप में जोड़ना, और यह संख्या गुणा करना और कई बार एक स्ट्रिंग दोहराना दोनों "गुणात्मक" संचालन हैं। –

5

यहां एक उदाहरण है जो यूनिक्स पाइपलाइन अनुकरण करने के लिए बिटवाई या ऑपरेशन का उपयोग करता है। यह अंगूठे के अधिकांश नियमों के लिए एक काउंटर उदाहरण के रूप में है।

मैं सिर्फ Lumberjack जो वास्तविक कोड



class pipely(object): 
    def __init__(self, *args, **kw): 
     self._args = args 
     self.__dict__.update(kw) 

    def __ror__(self, other): 
     return (self.map(x) for x in other if self.filter(x)) 

    def map(self, x): 
     return x 

    def filter(self, x): 
     return True 

class sieve(pipely): 
    def filter(self, x): 
     n = self._args[0] 
     return x==n or x%n 

class strify(pipely): 
    def map(self, x): 
     return str(x) 

class startswith(pipely): 
    def filter(self, x): 
     n=str(self._args[0]) 
     if x.startswith(n): 
      return x 

print"*"*80 
for i in xrange(2,100) | sieve(2) | sieve(3) | sieve(5) | sieve(7) | strify() | startswith(5): 
    print i 

print"*"*80 
for i in xrange(2,100) | sieve(2) | sieve(3) | sieve(5) | sieve(7) | pipely(map=str) | startswith(5): 
    print i 

print"*"*80 
for i in xrange(2,100) | sieve(2) | sieve(3) | sieve(5) | sieve(7) | pipely(map=str) | pipely(filter=lambda x: x.startswith('5')): 
    print i 

+0

+1 क्योंकि यह बहुत दिलचस्प है, भले ही मुझे नहीं पता कि मैं इसे वास्तविक कोड में उपयोग करने की स्वीकृति देता हूं या नहीं। –

+2

:) मैं व्यवस्थापक मैंने इसे वास्तविक कोड में उपयोग नहीं किया है, लेकिन यह एक साथ श्रृंखला जनरेटर के लिए एक आसान तरीका है। आप सह-दिनचर्या के समान कुछ कर सकते हैं, लेकिन सिंटैक्स ' चलनी (2, चलनी (3, चलनी (5, चलनी (7))) की तरह अधिक हो जाता है) 'जो मुझे –