python - पायथन में ऑपरेटर ओवरलोडिंग: मापदंडों के विभिन्न प्रकारों और आदेशों को नियंत्रित करना




class operator-overloading (2)

आपको __rmul__ को भी लागू __rmul__ जब शुरुआती कॉल को int.__mul__(7, v) विफल रहता है, तो पायथन अगले type(v).__rmul__(v, 7) प्रयास करेगा type(v).__rmul__(v, 7)

def __rmul__(self, lhs):
    return self * lhs  # Effectively, turn 7 * v into v * 7

जैसा कि रॉइंग बताते हैं, आप इस परिभाषा के लिए बस __rmul__ = __mul__ लिख सकते हैं। __rmul__ गैर-कम्यूटेटिक गुणन के लिए अनुमति देने के लिए मौजूद है जहां बस __mul__ को उलट कर दिया गया ऑपरेंड के साथ पर्याप्त नहीं है।

उदाहरण के लिए, यदि आप Matrix क्लास लिख रहे थे और नेस्टेड सूची द्वारा गुणा समर्थन करना चाहते थे, उदाहरण के लिए,

m = Matrix(...)  # Some 2 x 2 matrix
n = [[1, 2], [3,4]]
p = n * m

यहां, list वर्ग को Matrix आवृत्ति से एक सूची के बारे में कितनी जानकारी नहीं होगी, इसलिए जब list.__mul__(n, m) विफल हो जाती है, तो अजगर Matrix.__rmul__(m, n) प्रयास करेगा Matrix.__rmul__(m, n) । हालांकि, n * m और m * n सामान्य रूप से दो अलग-अलग परिणाम होते हैं, इसलिए Matrix.__rmul__(m, n) != Matrix.__mul__(m, n) ; सही उत्तर उत्पन्न करने के लिए __rmul__ को थोड़ा अतिरिक्त काम करना है।

इस सवाल का पहले से ही उत्तर दिया गया है:

मेरे पास एक साधारण वर्ग है जो कि वैक्टर पर गणितीय संचालन (संख्याओं की सूची) के साथ मदद करता है। मेरे Vector को Vector या एक स्केलर ( float या int ) के अन्य उदाहरणों से गुणा किया जा सकता है

दूसरे में, अधिक जोरदार टाइप किया गया, भाषाओं में मैं दो vector को गुणा करने के लिए एक विधि बनाऊँगा और एक vector द्वारा और int / float को गुणा करने के लिए एक अलग विधि। मैं अभी भी पायथन के लिए बहुत नया हूँ और मुझे यकीन नहीं है कि मैं इसे कैसे लागू करूंगा। एकमात्र तरीका मैं यह करने का विचार कर सकता है __mul__() ओवरराइड और आने वाले पैरामीटर की जांच कर रहा है:

class Vector(object):
  ...
 def __mul__(self, rhs):
  if isinstance(rhs, Vector):
     ...
  if isinstance(rhs, int) or isinstance(rhs, float):
    ...

यहां तक ​​कि अगर मैं इस तरह से करता हूँ, तो मुझे इस तरह एक स्केलर द्वारा Vector को गुणा करने के लिए मजबूर किया जाएगा:

v = Vector([1,2,3])

result = v * 7

क्या होगा अगर मैं गुणा में ऑपरेंडों के क्रम को बदलना चाहता हूं?

result = 7 * v

पायथन में ऐसा करने का सही तरीका क्या है?


उलट कार्रवाई के लिए विशेष तरीके हैं:

  • __rmul__ के पीछे के लिए __mul__
  • और __radd__ लिए __add__ ,
  • ...

इन्हें कहा जाता है कि जब बाएं हाथ के ऑपरेटर को सामान्य ऑपरेशन के लिए रिटर्न नहीं देता है (इसलिए ऑपरेशन 2 + vector_instance पहले प्रयास करेगा: (2).__add__(vector_instance) लेकिन अगर यह रिटर्न NotImplemented तो vector_instance.__radd__(2) NotImplemented तो vector_instance.__radd__(2) को कहा जाता है)।

हालांकि मैं अंकगणित विशेष विधियों में isinstance चेक का उपयोग नहीं isinstance , जो बहुत सारे कोड पुनरावृत्ति के लिए प्रेरित करेगा।

आप वास्तव में __init__ में एक विशेष मामला बना सकते हैं और स्केलर से Vector को एक रूपांतरण लागू कर सकते हैं:

class Vector(object):
    def __init__(self, x, y=None, z=None):
        if y is None and z is None:
            if isinstance(x, Vector):
                self.x, self.y, self.z = x.x, x.y, x.z
            else:
                self.x, self.y, self.z = x, x, x
        elif y is None or z is None:
            raise ValueError('Either x, y and z must be given or only x')
        else:
            self.x, self.y, self.z = x, y, z

    def __mul__(self, other):
        other = Vector(other)
        return Vector(self.x*other.x, self.y*other.y, self.z*other.z)

    __rmul__ = __mul__   # commutative operation

    def __sub__(self, other):
        other = Vector(other)
        return Vector(self.x-other.x, self.y-other.y, self.z-other.z)

    def __rsub__(self, other):   # not commutative operation
        other = Vector(other)
        return other - self

    def __repr__(self):
        return 'Vector({self.x}, {self.y}, {self.z})'.format(self=self)

यह अपेक्षा के अनुरूप काम करना चाहिए:

>>> 2 - Vector(1, 2, 3)
Vector(1, 0, -1)

>>> Vector(1, 2, 3) - 2
Vector(-1, 0, 1)

>>> Vector(1, 2, 3) * 2
Vector(2, 4, 6)

>>> 2 * Vector(1, 2, 3)
Vector(2, 4, 6)

ध्यान दें कि यह एक त्वरित और गंदे मसौदा था (जो कई बग हो सकता है)। मैं सिर्फ "सामान्य विचार" पेश करना चाहता था कि कैसे प्रत्येक अंकगणितीय ऑपरेशन में टाइप को विशेष आवरण के बिना हल किया जा सकता है।







operators