首页 文章

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

提问于
浏览
1

我正在尝试实现扩展类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 回答

  • 1

    首先,您在 __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
    
  • 5

    这里有两个问题

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

相关问题