2011-03-03 14 views
32

कहें कि मेरी एक सूची l है। किस परिस्थिति में l.__rmul__(self, other) कहा जाता है?किस परिस्थितियों में __rmul__ कहा जाता है?

मैं मूल रूप से प्रलेखन को समझ गया, लेकिन मैं किसी भी संदेह से परे अपने उपयोग को स्पष्ट करने के लिए एक उदाहरण भी देखना चाहूंगा।

उत्तर

83

जब पायथन दो वस्तुओं को गुणा करने का प्रयास करता है, तो यह पहले बाएं ऑब्जेक्ट की __mul__() विधि को कॉल करने का प्रयास करता है। यदि बाएं ऑब्जेक्ट में __mul__() विधि नहीं है (या विधि NotImpemented लौटाती है, यह दर्शाती है कि यह सही ऑपरेंड के साथ काम नहीं करता है), तो पाइथन जानना चाहता है कि सही वस्तु गुणा कर सकती है या नहीं। यदि दायां ऑपरेंड बाएं जैसा ही प्रकार है, तो पायथन जानता है कि यह नहीं कर सकता है, क्योंकि यदि बायां वस्तु इसे नहीं कर सकती है, तो उसी प्रकार का एक और ऑब्जेक्ट निश्चित रूप से नहीं हो सकता है।

यदि दो ऑब्जेक्ट्स अलग-अलग प्रकार हैं, हालांकि, पायथन का आंकड़ा यह शॉट के लायक है। हालांकि, ऑपरेशन कम नहीं होने पर, सही ऑब्जेक्ट को बताने के लिए इसे किसी भी तरीके की आवश्यकता है कि ऑपरेशन में सही ऑब्जेक्ट है। (गुणन निश्चित रूप से है, लेकिन सभी ऑपरेटरों नहीं हैं, और किसी भी मामले में * हमेशा गुणा के लिए उपयोग नहीं किया जाता है!) तो यह __mul__() के बजाय __rmul__() पर कॉल करता है।

उदाहरण के लिए, पर विचार के बाद दो बयान:

print "nom" * 3 
print 3 * "nom" 

पहले मामले में, अजगर स्ट्रिंग के __mul__() प्रणाली को बुलाती है। स्ट्रिंग जानता है कि एक पूर्णांक से खुद को गुणा कैसे करें, इसलिए सब ठीक है। दूसरे मामले में, पूर्णांक को स्ट्रिंग द्वारा खुद को गुणा करने के बारे में नहीं पता है, इसलिए __mul()__NotImplemented देता है और स्ट्रिंग का __rmul()__ कहा जाता है। यह जानता है कि क्या करना है, और आपको पहले मामले के समान परिणाम मिलते हैं।

अब हम देख सकते हैं __rmul()__ की अनुमति देता है कि स्ट्रिंग के विशेष गुणा व्यवहार के सभीstr वर्ग में समाहित किया जाना करने के लिए (जैसे पूर्णांक के रूप में) इस तरह के अन्य प्रकार है कि, गुणा करने के लिए सक्षम होने के लिए तार बारे में कुछ पता करने की जरूरत नहीं उनके द्वारा। अब से सौ साल (मान लीजिए कि पाइथन अभी भी उपयोग में है) आप एक नए प्रकार को परिभाषित करने में सक्षम होंगे जिसे किसी भी क्रम में पूर्णांक द्वारा गुणा किया जा सकता है, भले ही int वर्ग को एक शताब्दी से अधिक समय तक इसका कुछ भी पता न हो।

वैसे, स्ट्रिंग क्लास की __mul__() पाइथन के कुछ संस्करणों में एक बग है। यदि यह किसी वस्तु द्वारा स्वयं को गुणा करने के बारे में नहीं जानता है, तो यह NotImplemented लौटने के बजाय TypeError उठाता है।इसका अर्थ यह है कि आप किसी उपयोगकर्ता द्वारा परिभाषित प्रकार द्वारा स्ट्रिंग को गुणा नहीं कर सकते हैं, भले ही उपयोगकर्ता द्वारा परिभाषित प्रकार में __rmul__() विधि हो, क्योंकि स्ट्रिंग को कभी भी मौका नहीं मिलता है। उपयोगकर्ता द्वारा परिभाषित प्रकार को पहले जाना होगा (उदा। Foo() * 'bar''bar' * Foo() के बजाय) इसलिए __mul__() कहा जाता है। ऐसा लगता है कि उन्होंने इसे पायथन 2.7 में तय किया है (मैंने इसे पायथन 3.2 में भी परीक्षण किया है), लेकिन पायथन 2.6.6 में बग है।


+2

पिछले स्वीकृत उत्तर के साथ कुछ भी गलत नहीं है, लेकिन यदि कोई भविष्य में यहां पर पॉप करता है, तो शायद वे इस उत्तर में शीर्ष पर चलना चाहते हैं, इसलिए मैं इसके बजाय इसे स्वीकार करूंगा। – porgarmingduod

+1

++, उत्कृष्ट उत्तर - मैंने कुछ सीखा :) –

+0

दयालु ने कहा: यह शायद अब बर्बाद प्रयास है कि आपने एक जवाब स्वीकार कर लिया है, लेकिन: मैं आपको आश्वस्त करना चाहता हूं कि आपका प्रयास बर्बाद नहीं हुआ - मुझे समस्या थी वेक्टर बीजगणित में __rmul__ उपयोग (वैक्टरों के स्केलर गुणा के लिए) को सक्षम करना। आपका स्पष्टीकरण मुझे यह समझाने के लिए पर्याप्त था कि (स्केलर) * (वेक्टर) ऑपरेशन के मामले में __mul__ विधि को __rmul__ विधि पर जाने के लिए कॉल सक्षम करने के लिए __mul__ विधि को या तो "लागू नहीं किया गया इरर()" या "वापसी लागू नहीं किया गया" के साथ समाप्त होना चाहिए। आपके सहयोग के लिए धन्यवाद! – user377367

7

बाइनरी ऑपरेटरों को उनके प्रकृति के दो ऑपरेंड हैं। प्रत्येक ऑपरेंड ऑपरेटर के बाएं या दाएं तरफ हो सकता है। जब आप किसी प्रकार के ऑपरेटर को अधिभारित करते हैं, तो आप ऑपरेटर के किनारे ओवरलोडिंग के लिए निर्दिष्ट कर सकते हैं। ऑपरेटर को विभिन्न प्रकार के दो ऑपरेटरों पर आक्रमण करते समय यह उपयोगी होता है। यहाँ एक उदाहरण है:

class Foo(object): 
    def __init__(self, val): 
     self.val = val 

    def __str__(self): 
     return "Foo [%s]" % self.val 


class Bar(object): 
    def __init__(self, val): 
     self.val = val 

    def __rmul__(self, other): 
     return Bar(self.val * other.val) 

    def __str__(self): 
     return "Bar [%s]" % self.val 


f = Foo(4) 
b = Bar(6) 

obj = f * b # Bar [24] 
obj2 = b * f # ERROR 

यहाँ, objval = 24 के साथ एक Bar हो जाएगा, लेकिन क्योंकि Bar कोई __mul__ है और Foo कोई __rmul__ है obj2 असाइनमेंट एक त्रुटि उत्पन्न करता है।

मुझे आशा है कि यह पर्याप्त स्पष्ट है।

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