सवाल पायथन में "+ =" ओवरराइडिंग? (__iadd __ () विधि)


क्या पाइथन में + = ओवरराइड करना संभव है?


44
2018-06-26 02:04


मूल


का सही डुप्लिकेट stackoverflow.com/questions/728361/... - Scott Griffiths
हां, लेकिन साइट खोज का उपयोग करने के लिए: + = पायथन कोई परिणाम नहीं देता है। "+ =" के आस-पास उद्धरण डालने से परिणाम मिलते हैं लेकिन मुख्य रूप से शीर्षक से अप्रासंगिक निर्णय लेते हैं। हालांकि इसे Google खोज के माध्यम से मिला। - jcomeau_ictx


जवाब:


हाँ, ओवरराइड करें __iadd__ तरीका। उदाहरण:

def __iadd__(self, other):
    self.number += other.number
    return self    

81
2018-06-26 02:08



आपको लागू नहीं करना चाहिए __iadd__ यदि आपकी कक्षा अपरिवर्तनीय वस्तुओं का प्रतिनिधित्व करती है। उस मामले में बस लागू करें __add__ जिसका उपयोग ओवरराइड करने के लिए किया जाएगा += बजाय। उदाहरण के लिए आप उपयोग कर सकते हैं += तारों और पूर्णांक जैसे अपरिवर्तनीय प्रकारों पर, जिनका उपयोग नहीं किया जा सका __iadd__। - Scott Griffiths
@ स्कॉट ग्रिफिथ्स, तो आप कह रहे हैं कि अगर आपने कार्यान्वित किया है __add__ आपको जरूरी नहीं है कि आपको लागू करना पड़े __iadd__? मैंने आपके द्वारा लिंक किए गए डुप्लिकेट प्रश्न को पढ़ा लेकिन मुझे अभी उलझन में आया क्योंकि मुझे समझ में नहीं आता कि आप क्यों लागू करेंगे __add__ ताकि यह वस्तु को बदल देता है - Josie Thompson
@ स्कॉट ग्रिफिथ्स का मतलब है "आपको जरूरी नहीं है कि आपको लागू करना पड़े __iadd__  + = का उपयोग करने के लिए? " - Josie Thompson
@ जोसी थॉम्पसन: यदि आप लागू नहीं करते हैं __iadd__तो यह उपयोग करेगा __add__ यदि उपलब्ध हो, जो आमतौर पर ठीक है। तो उस मामले में a += b के बराबर होगा a = a + b, जो एक नया मूल्य असाइन करता है a बदलने के बजाय a अपने आप। एक अलग होना __iadd__ आमतौर पर आपको उपयोग करने की आवश्यकता के बजाय एक अच्छा अनुकूलन है += ऑपरेटर। - Scott Griffiths
@ScottGriffiths के लिए एक ही सच है __imul__? - Chris_Rands


ऊपर दिए गए उत्तरों में सही तरीके से दिए गए अनुसार, यह स्पष्ट रूप से स्पष्ट करने के लायक है कि कब __iadd__ अतिरंजित है, द x += y ऑपरेशन के अंत के साथ खत्म नहीं होता है __iadd__ तरीका।

इसके बजाए, यह समाप्त होता है x = x.__iadd__(y)। दूसरे शब्दों में, पायथन आपके रिटर्न वैल्यू को असाइन करता है __iadd__ कार्यान्वयन पूरा होने के बाद, उस वस्तु को कार्यान्वित करना जो आप "जोड़ रहे हैं"।

इसका मतलब है कि बाईं तरफ मुक्ति करना संभव है x += y ऑपरेशन ताकि अंतिम निहित कदम विफल हो जाए। गौर करें कि जब आप किसी सूची में शामिल हो रहे हैं तो क्या हो सकता है:

>>> x[1] += y # x has two items

अब, अगर आपका __iadd__ कार्यान्वयन (एक वस्तु का एक तरीका x[1]) गलती से या उद्देश्य पर पहली वस्तु को हटा देता है (x[0]) सूची की शुरुआत से, पाइथन फिर आपके चलाएगा __iadd__ विधि) और इसके वापसी मूल्य को असाइन करने का प्रयास करें x[1]। जो अब अस्तित्व में नहीं रहेगा (यह होगा x[0]), जिसके परिणामस्वरूप एक ÌndexError

या, अगर आपका __iadd__ शुरू करने के लिए कुछ प्रविष्टियां x उपर्युक्त उदाहरण में, आपका ऑब्जेक्ट होगा x[2], नहीं x[1], और जो कुछ भी पहले था x[0] अब पर होगा x[1]और के वापसी मूल्य असाइन किया जाना चाहिए __iadd__ मंगलाचरण।

जब तक कोई यह नहीं समझता कि क्या हो रहा है, जिसके परिणामस्वरूप बग ठीक करने के लिए एक दुःस्वप्न हो सकता है।


13
2017-07-21 18:18





अधिभार के अलावा __iadd__ (स्वयं को वापस याद रखना!), आप भी फॉलबैक कर सकते हैं __add__, x + = y x = x + y की तरह काम करेगा। (यह + = ऑपरेटर के नुकसान में से एक है।)

>>> class A(object):
...   def __init__(self, x):
...     self.x = x
...   def __add__(self, other):
...     return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False

यहां तक ​​कि विशेषज्ञों की यात्रा:

class Resource(object):
  class_counter = 0
  def __init__(self):
    self.id = self.class_counter
    self.class_counter += 1

x = Resource()
y = Resource()

आप किस मूल्य की अपेक्षा करते हैं x.id, y.id, तथा Resource.class_counter रखने के लिए?


12
2018-06-26 02:26



आपके दूसरे उदाहरण में iadd या + = के साथ कुछ लेना देना नहीं है। वही परिणाम तब होता है जब आप self.class_counter = self.class_counter + 1 का उपयोग करते हैं, यह केवल एक स्कोपिंग समस्या है, जब संसाधन का उपयोग किया जाना चाहिए। - FogleBird
यह एक उदाहरण है कि + = का उपयोग करने से समस्याओं का कारण बन सकता है। यदि आप ओवरलोडिंग कर रहे हैं मैं जोड़ना, तो आप अपनी कक्षा (स्वयं सहित) के उपयोगकर्ताओं को खोल रहे हैं, और, कम से कम, आपको पता होना चाहिए कि समस्या पहले से मौजूद है।
@FogleBird: यह एक गॉचा है क्योंकि foo += bar या तो "मौजूदा वस्तु को बदल सकते हैं foo "या" असाइन करने के लिए संदर्भित करता है foo अभिव्यक्ति से उत्पन्न वस्तु के लिए foo + bar"और जो होता है इस पर निर्भर करता है कि क्या foo एक है __iadd__ तरीका। - Claudiu


http://docs.python.org/reference/datamodel.html#emulating-numeric-types

उदाहरण के लिए, कथन निष्पादित करने के लिए   एक्स + = वाई, जहां एक्स एक का उदाहरण है   कक्षा जिसमें __iadd __ () विधि है,   x .__ iadd __ (y) कहा जाता है।


5
2018-06-26 02:09