__add__支持添加不同类型?

__add__ to support addition of different types?

如果 python 是一种支持重载的静态编程语言,那将很容易解决。我正在制作一个名为 Complex 的 class,它是复数的表示(我知道 python 有它自己的,但我想自己制作一个),其中 a 是实数,b 是虚数(Complex(a, b))。它应该支持将 Complex 实例加在一起 ​​(Complex(2, 4) + Complex(4, 5) = Complex(6, 9)),以及添加一个整数 (Complex(2, 3) + 4 = Complex(6, 3))。但是,由于 python...

的性质
__add__(self, other):

...我必须选择 class 支持的类型,因为它不会在编译时识别类型,也不支持函数重载。什么是最好的解决方案?我是否必须编写与 other 参数的数据类型相关的 if 语句?

这里有什么问题?

您始终可以检查 python 对象的类型:

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

混合类型操作

Python中的numbers模块可以用来实现你自己的号码classes。除其他外,它 allows to correctly implement mixed-types operations 使用 __add____radd__

例子

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

实施新的号码类型

如果你想实现一个与 Python 内置数字类型一起工作的数字 class,你可以通过 sub[ 实现你自己的 Complex class =48=]ing 抽象基础 class numbers.Complex.

这个抽象基础 class 将强制实施所需的方法 __abs____add____complex____eq____mul__ , __neg__, __pos__, __pow__, __radd__, __rmul__, __rpow__, __rtruediv__, __truediv__, conjugateimagreal.

你可以做的是检查是否存在 Complex 实例,如果不是,则将其变成一个,如下所示:

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

这当然不会消除类型检查,但它会重复使用您在 __init__ 中所做的任何事情(这可能是检查输入是 int 还是 float)。

如果此时您不在 init 中进行类型检查,这可能是个好主意,并且 this 看起来合理,除了内置的复杂类型。

使用 isinstance 检查它是否是同一类型,如果不是则假设它是任何类型的数字:

  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__)

不一定有最佳解决方案。不过,在这种特殊情况下:

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

可能是要走的路(尽管我在这里对你的 Complex class 做了很多假设)。如果 other 已经是 Complex,则 make_complex 函数 returns 它。如果不是,它会尽力转换(例如,通过构造一个虚部为零的复数,将一个实数对变成一个复数对)。如果失败,它会引发一些合适的异常。

这个make_complex也适用于Complex的构造函数中,这样就可以替换部分:

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

与:

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

例如。 (您可以只使用 Complex 构造函数完成所有工作,使用 isinstance() 适当地检查参数类型。)

请注意,由于复数加法是可交换的,您可能希望也实现 __radd__