I'm trying to implement the __mul__
method 开发者_开发问答of class C
which extends class P
. Class P
has an implementation of __mul__
but that's only for elements of that type (P() * P()
).
So in C.__mul__
I want to implement simple multiplication for a float when the argument is float. When it's not I want to use P.__mul__
... but that leads to problems as in P.__mul__
that's a return P(something)
...
So basically the fact that they were originally of type C
is lost after some operations.
The following code better explain the issue.
Any idea fix this?
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
First you your typecheck in __mul__
for MyFloatExt
should look like
isinstance(other,(int,long,float))
or even better
isinstance(other,Number) #from numbers import Number
Also you would like to change definition of __mul__
in MyFloat
to this:
class MyFloat(object):
#...
def __mul__(self, other):
return type(self)(self.a * other.a)
#...
so it can create instances of your actual type
And you can prefer call super
instead of calling MyFloat.__mul__
with reasons of evolution your type hierarchies.
full source:
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
Two problems here
In your
__mul__
implementation ofMyFloatExt
you're never checking ifother
is an instance ofMyFloatExt
isinstance(e, MyFloat)
will always be true, becauseMyFloatExt
inherits fromMyFloat
To fix it:
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)
精彩评论