An inheritance example in Python
I'm not clear how to pose this question. If I did, I'd probably be a lot closer to a solution.. I need some insight into inheritance.
I want to make a custom subtype of float
. But I want the instance of this subtype to re-evaluate its value before performing any of the normal float methods (__add__
,__mul__
, etc..). In this example it should multiply its value by the global FACTOR:
class FactorFloat(float):
# I don't think I want to do this:
## def __new__(self, value):
## return float.__new__(self, value)
def __init__(self, value):
float.__init__(self, value)
# Something important is missing..
# I want to do something with global FACTOR
# when any float method is called.
f = FactorFloat(3.)
FACTOR = 10.
print f # 30.0
print f-1 # 29.0
FACTOR = 2.
print f # 6.0
print f-1 # 5.0
This is a just a sanitized example that I think gets my point across. 开发者_运维问答 I'll post a more complex "real" problem if necessary.
class FactorFloat(float):
def _factor_scale(f):
def wrapper(self, *args, **kwargs):
scaled = float.__mul__(self, FACTOR)
result = f(scaled, *args, **kwargs)
# if you want to return FactorFloats when possible:
if isinstance(result, float):
result = type(self)(result/FACTOR)
return result
return wrapper
def __repr__(self):
return '%s(%s)' % (type(self).__name__, float.__repr__(self))
__str__ = _factor_scale(float.__str__)
__mul__ = _factor_scale(float.__mul__)
__div__ = _factor_scale(float.__div__)
__add__ = _factor_scale(float.__add__)
__sub__ = _factor_scale(float.__sub__)
f = FactorFloat(3.)
FACTOR = 10.
print f # 30.0
print f-1 # 29.0
FACTOR = 2.
print f # 6.0
print f-1 # 5.0
print repr(f)
for:
30.0
29.0
6.0
5.0
FactorFloat(3.0)
EDIT:
In response to the question in the comment; making things slightly more general and automated, using a class decorator. I would not loop over dir(baseclass)
, but instead would explicitly list the methods I wished to wrap. In the example below, I list them in the class variable _scale_methods
.
def wrap_scale_methods(cls):
Base = cls.__base__
def factor_scale(f):
def wrapper(self, *args, **kwargs):
scaled = Base.__mul__(self, FACTOR)
result = f(scaled, *args, **kwargs)
if isinstance(result, Base):
result = type(self)(result/FACTOR)
return result
return wrapper
for methodname in cls._scale_methods:
setattr(cls, methodname, factor_scale(getattr(Base, methodname)))
return cls
@wrap_scale_methods
class FactorComplex(complex):
_scale_methods = '__str__ __mul__ __div__ __add__ __sub__'.split()
def __repr__(self):
return '%s(%s)' % (type(self).__name__, complex.__repr__(self)[1:-1])
What you're wanting to do is actually very hard. I do not know of any python software that subclasses a type such as float
or int
and then does mathematics with it. I think that perhaps there is a better way to accomplish what you're trying to achieve without using a subclass of float
. You should investigate alternatives.
Here are a couple of methods to get your testcases passing
def __str__(self):
return str(FACTOR*self)
def __sub__(self, other):
return self*FACTOR-other
obviously you have to also implement __add__
, __mul__
, etc...
Having said that - what is your use case? This seems like a weird thing to want to do
精彩评论