__add__ to support addition of different types?

一个人想着一个人 提交于 2020-04-13 07:15:24

问题


Would be very easy to solve had python been a static programming language that supported overloading. I am making a class called Complex which is a representation of complex numbers (I know python has its own, but i want to make one myself), where a is the real number and b is the imaginary (Complex(a, b)). It should support adding Complex instances together (Complex(2, 4) + Complex(4, 5) = Complex(6, 9)), as well as adding an integer (Complex(2, 3) + 4 = Complex(6, 3)). However, due to the nature of python...

__add__(self, other):

...I have to choose which the class will support, because it won't recognize types at compile-time, as well as not supporting overloading of functions. What is the best solution? Do I have to write an if statement in relation to the datatype of the other parameter?


回答1:


What you could do is check for the thing being of instance Complex, and if not, turn it into one, like so:

def __add__(self, other):
    if isinstance(other, Complex):
        # do addition
    else:
        return self + Complex(other, 0)

That of course does not eliminate type checking, but it reuses whatever you are doing in __init__ (which is probably checking if input is int or float).

If at the moment you do not do type checking in init, it is probably a good idea, and this looks reasonable, excepting built-in complex type.




回答2:


There is not necessarily a best solution. In this particular case, though:

def __add__(self, other):
    c = make_complex(other)
    return Complex(self.real + c.real, self.imag + real.imag)

is probably the way to go (though I'm making lots of assumptions about your Complex class here). If other is already Complex, the make_complex function returns it. If not, it tries its best to convert (e.g., to turn a real-only into a complex pair by constructing a complex with a zero imaginary part). If that fails, it raises some suitable exception.

This make_complex is also suitable in the constructor for Complex, so that you can replace parts of:

e = Complex(1.718, 0) # e (well, not very exactly)
i = Complex(0, 1) # sqrt(-1)
pi = Complex(3.14, 0) # pi
# you know what to do next

with:

e = Complex(1.718)
pi = make_complex(3.14)

for instance. (You can just use the Complex constructor to do all the work, using isinstance() to check the argument types as appropriate.)

Note that since complex addition is commutative you may wish to implement __radd__ as well.




回答3:


Use isinstance to check if it's the same Type if not assum it's any type of number:

  def __add__(self, other):
       # it's the same class
       if isinstance(other, Complex):
            # and you should return the same class 
            # if anyone extend your class SomeClass(Complex): you should return SomeClass not Complex Object
            return self.__class__(self.a + other.a, self.b + other.b)

       # assuming is any type of number
       try:
         return self.__class__(int(self.a + other), self.b)
       except TypeError:
         # change the error message
         raise TypeError("unsupported operand type(s) for +: '%s' and '%s'" % (self.__class__, other.__class__)



回答4:


Mixed-types operations

The numbers module in Python can be used to implement you own number classes. Among other things it allows to correctly implement mixed-types operations using __add__ and __radd__

Example

import numbers

class Complex:
    def __add__(self, other):
        if isinstance(self, Complex):
            ...
        elif isinstance(other, numbers.Real):
            ...
        else:
            raise TypeError

    def __radd__(self, other):
        return self + other

Implemention new number types

If you want to implement a number class which works along with Python built-in number types, you can implement your own Complex class by subclassing the abstract base class numbers.Complex.

This abstract base class will enforce the implementation of the needed methods __abs__, __add__, __complex__, __eq__, __mul__, __neg__, __pos__, __pow__, __radd__, __rmul__, __rpow__, __rtruediv__, __truediv__, conjugate, imag and real.




回答5:


What's the problem here?

You can always check the type of a python object:

if type(other) != type(self):
    # raise some error
# do addition
return 


来源:https://stackoverflow.com/questions/57829402/add-to-support-addition-of-different-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!