当继承基类型时,如float,是否可以“重新计算”或“重新分配”原始值?如果我有以下类定义,
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)
当我开始
>>> ma = MovingAverage(10, 3)
>>> ma
10.0
但
>>> ma.add(3)
6.5
>>> ma
10.0
我尝试过的另一个类定义是:
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)
这一次,当我开始
>>> ma = MovingAverage([10], 3)
>>> ma
10.0
和
>>> ma.add(3)
6.5
>>> ma
10.0
>>> ma = ma.add(3)
>>> ma
5.333333333333333
然而,我认为(我没有测试过发现)它会让这个显着变慢。那么,可以做到吗?我可以以某种方式设置它,以便ma
的返回值是我正在寻找的值吗?或者我是否需要定义value
属性,将基类更改为object
,并放弃我有机会控制类的返回值的假装?
答案 0 :(得分:5)
没有。由于这些类型是不可变的,因此您应该使用封装,而不是继承。
答案 1 :(得分:2)
我不认为伊格纳西奥斯上面的回答需要任何改进,但是因为我有这个课程,我以为我应该分享。它避免了多次执行大额操作,并避免了使用(更多)天真算法时可能出现的舍入错误:
class MovingAverage:
def __init__(self):
self.sum = None
self.num = 0
def add(self, val):
if self.sum is None:
self.sum = val
else:
self.sum += val
self.num += 1
return self.val
@property
def val(self):
if self.sum is None:
return None
else:
return self.sum/self.num
if __name__ == "__main__":
print("Running small test suite")
fail = False
m = MovingAverage()
try:
assert m.val is None, "A new MovingAverage should be None"
assert m.add(10) == 10, "New average should be returned"
assert m.val == 10, "The average should update for each add"
assert m.add(20) == 15, "New average should be returned"
assert m.val == 15, "The average should update for each add"
assert m.add(0) == 10, "Adding zero should work"
assert m.add(-10) == 5, "Adding a negative number should work"
assert m.add(-1) == 19/5, "Result should be able to be a fraction"
except AssertionError as e:
print("Fail: %s" % e.args[0])
fail = True
if not fail: print("Pass")