我可以更改 python 子类中的基类值吗?
当子类化基本类型(例如 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
but
>>> 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
and
>>> ma.add(3)
6.5
>>> ma
10.0
>>> ma = ma.add(3)
>>> ma
5.333333333333333
开始时,我认为(我还没有测试发现)这使得这显着慢点。那么,可以吗?我可以以某种方式设置它,以便从 ma
返回的值就是我正在寻找的值吗?或者我是否需要定义一个 value
属性,将基类更改为 object
,并放弃我有机会控制该类的返回值的假象?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不可以。由于这些类型是不可变的,因此您应该使用封装,而不是继承。
No. Since these types are immutable, you should be using encapsulation, not inheritance.
我不认为上面的 Ignacios 答案需要任何改进,但由于我有这门课,我只是认为我应该分享。它避免了多次进行大和运算,还避免了使用(更)幼稚的算法时可能出现的舍入错误:
I don't think that Ignacios answer above needs any improvements, but since I had this class laying around I just thought I should share. It avoids doing big sum operations many times and also avoids rounding errors that might occur if you use a (more) naïve algorithm: