python - 同时重载多个运算符
我有一个自定义的类,想要重载几个数学运算符,但我在想有没有办法避免一个一个写代码。我找不到不需要逐个重载每个运算符的例子。
class Foo(object):
a=0
def __init__(self, a):
self.a=a
def __add__(self, other):
#common logic here
return Foo(self.a+other.a)
def __sub__(self, other):
#common logic here
return Foo(self.a-other.a)
def __mul__(self, other):
#common logic here
return Foo(self.a*other.a)
#etc...
逻辑比这稍微复杂一点,但通常的做法是每个运算符重载的方法里都有一些相同的代码,用来检查这个操作是否允许,然后再用类里的成员来构建操作。我想减少这些重复的代码。这种做法是可行的:
class Foo(object):
a=0
def __init__(self, a):
self.a=a
def operate(self, other, operator):
#common logic here
a = constructOperation(self.a, other.a, operator)
return Foo(a)
def __add__(self, other):
return self.operate(other, "+")
def __sub__(self, other):
return self.operate(other, "-")
def constructOperation(operand0, operand1, operator):
if operator=="+":
return operand0 + operand1
if operator=="-":
return operand0 - operand1
不过这样手动构建操作感觉有点傻。这样做合理吗?还是说有什么更好的方法呢?
4 个回答
1
我不知道有没有办法避免定义所有(或者至少大部分)运算符。这样做是有道理的,毕竟,给定 __add__
(加法)和 __mul__
(乘法),并没有一种唯一的方法来定义 __sub__
(减法)。
不过,有一个改进的建议是,可以把可调用的函数传递给 constructOperation(),而不是使用符号运算符。
例如:
class Foo(object):
a=0
def __init__(self, a):
self.a=a
def operate(self, other, operator):
#common logic here
a = constructOperation(self.a, other.a, operator)
return Foo(a)
def __add__(self, other):
return self.operate(other, sum)
def __sub__(self, other):
return self.operate(other, lambda x, y: x - y)
def constructOperation(operand0, operand1, operator):
return operator(operand0, operand1)
5
我建议直接使用operator
这个模块:
import operator
class Foo(object):
a=0
def __init__(self, a):
self.a=a
def operate(self, other, op):
#common logic here
return Foo(op(self.a, other.a))
def __add__(self, other):
return self.operate(other, operator.add)
def __sub__(self, other):
return self.operate(other, operator.sub)
7
你可以通过反射和高阶函数来实现这个功能,不过这样做可能和继承不太兼容。
import operator
def apply_a(func):
def inner(self, other):
return Foo(func(self.a, other.a))
return inner
class Foo(object):
def __init__(self, a=0):
self.a = a
for name in ['__add__','__mul__','__sub__']:
setattr(Foo, name, apply_a(getattr(operator, name)))