__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__
, conjugate
、imag
和 real
.
你可以做的是检查是否存在 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__
。
如果 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__
, conjugate
、imag
和 real
.
你可以做的是检查是否存在 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__
。