问题
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