使用父实现从子类覆盖__mul__:导致问题

我正在尝试实现扩展类P的类C的__ mul 方法 . 类P具有 mul __的实现,但这仅适用于该类型的元素(P()* P()) .

所以在C __ mul 中我想在参数为float时为float实现简单乘法 . 当它不是我想要使用P的 mul __ ..但这导致问题,如在P的__ mul __那是“返回P(某事)”..

所以基本上他们最初是C型的事实在一些操作之后就会丢失 .

以下代码更好地解释了该问题 .

任何想法解决这个?

class MyFloat(object):
  def __init__(self, a):
    self.a = a

  def __mul__(self, other):
    return MyFloat(self.a * other.a)

  def __repr__(self):
    return str(self.a)


class MyFloatExt(MyFloat):
  def __init__(self, a):
    MyFloat.__init__(self, a)

  def __add__(self, other):
    return MyFloatExt(self.a + other.a)

  def __mul__(self, other):
    if type(other) == (int, long, float):
      return MyFloatExt(self.a * other)
    else:
      return MyFloat.__mul__(self, other)

a = MyFloatExt(0.5)
b = MyFloatExt(1.5)

c = a + b
print c

d = a * b
print d

e = d * c
print e

print isinstance(e, MyFloat)
f = e * 0.5
print f

回答(2)

2 years ago

首先,您在 __mul__ 中的 MyFloatExt 的类型检查应该是这样的

isinstance(other,(int,long,float))

甚至更好

isinstance(other,Number) #from numbers import Number

您还想在 MyFloat 中将 __mul__ 的定义更改为:

class MyFloat(object):
#...
  def __mul__(self, other):
    return type(self)(self.a * other.a)
#...

所以它可以创建您的实际类型的实例

你可以更喜欢调用 super 而不是调用 MyFloat.__mul__ ,因为你的类型层次结构是进化的原因 .

完整来源:

from numbers import Number
class MyFloat(object):
  def __init__(self, a):
    self.a = a

  def __mul__(self, other):
    return type(self)(self.a * other.a)

  def __repr__(self):
    return str(self.a)


class MyFloatExt(MyFloat):
  def __init__(self, a):
    super(MyFloatExt,self).__init__(a)

  def __add__(self, other):
    return type(self)(self.a + other.a)

  def __mul__(self, other):
    if isinstance(other,Number):
      return type(self)(self.a * other)
    else:
      return super(MyFloatExt,self).__mul__(other)


a = MyFloatExt(0.5)
b = MyFloatExt(1.5)

c = a + b
print c

d = a * b
print d


e = d * c
print e

print isinstance(e, MyFloat)

f = e * 0.5
print f

print map(type,[a,b,c,d,e,f]) == [MyFloatExt]*6

2 years ago

这里有两个问题

  • MyFloatExt__mul__ 实现中,您永远不会检查 otherMyFloatExt 的实例

  • isinstance(e, MyFloat) 将永远为真,因为 MyFloatExt 继承自 MyFloat

要解决这个问题:

def __mul__(self, other):

    # check if we deal with a MyFloatExt instance
    if isinstance(other, MyFloatExt):
        return MyFloatExt(self.a * other.a)

    if type(other) == (int, long, float):
        return MyFloatExt(self.a * other)

    else:
        return MyFloat.__mul__(self, other)

# do the correct check
print isinstance(e, MyFloatExt)