Переопределение __mul__ из дочернего класса с использованием родительской реализации: приводит к проблемам - PullRequest
1 голос
/ 20 ноября 2010

Я пытаюсь реализовать метод __ mul __ класса C, который расширяет класс P. Класс P имеет реализацию __ mul __, но это только для элементов этого типа (P () * P ()).

Так что в C __ mul __ я хочу реализовать простое умножение для float, когда аргумент float. Когда это не так, я хочу использовать P __ mul __ .. но это приводит к проблемам, как в P __ mul __, это «return 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 ]

5 голосов
/ 20 ноября 2010

Сначала вы проверяете тип в __mul__ для MyFloatExt, должно выглядеть

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

или даже лучше

isinstance(other,Number) #from numbers import Number

Также вы хотели бы изменить определение __mul__в MyFloat к этому:

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
1 голос
/ 20 ноября 2010

Две проблемы здесь

  1. В вашей __mul__ реализации MyFloatExt вы никогда не проверяете, является ли other экземпляром MyFloatExt

  2. 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...