When subclassing a base type, like float, is it possible to “recalculate” or “reassign” the original value? If I have the following class definition,
import collections
class MovingAverage(float):
def __new__(self, initial_value, window):
self.d = collections.deque([initial_value], window)
return float.__new__(self, initial_value)
def add(self, new_value):
self.d.append(new_value)
print sum(self.d) / len(self.d)
# here, I want to _set_ the value of MovingAverage to
# sum(self.d) / len(self.d)
When I start with
>>> ma = MovingAverage(10, 3)
>>> ma
10.0
but
>>> ma.add(3)
6.5
>>> ma
10.0
The other class definition I’ve tried is this:
import collections
class MovingAverage(float):
def __new__(self, iterable, window):
self.d = collections.deque(iterable, window)
initial_value = sum(iterable) / len(iterable)
return float.__new__(self, initial_value)
def add(self, new_value):
self.d.append(new_value)
return MovingAverage(self.d, self.d.maxlen)
This time, when I start with
>>> ma = MovingAverage([10], 3)
>>> ma
10.0
and
>>> ma.add(3)
6.5
>>> ma
10.0
>>> ma = ma.add(3)
>>> ma
5.333333333333333
However, I think (I haven’t tested to find out) it makes this significantly slower. So, can it be done? Can I somehow set it so that the return from ma is the value that I’m looking for? Or do I need to define a value attribute, change the base class to object, and abandon my pretense that I have a chance of controlling the return value of the class?
No. Since these types are immutable, you should be using encapsulation, not inheritance.