创建一个看起来像浮点数的类对象
我想自己做一个简单的对象,用来跟踪变量的单位(也许我还会添加其他属性,比如公差)。这是我目前的进展:
class newVar():
def __init__(self,value=0.0,units='unknown'):
self.value=value
self.units=units
def __str__(self):
return str(self.value) + '(' + self.units + ')'
def __magicmethodIdontknow__(self):
return self.value
diameter=newVar(10.0,'m') #define diameter's value and units
print diameter #printing will print value followed by units
#intention is that I can still do ALL operations of the object
#and they will be performed on the self.value inside the object.
B=diameter*2
因为我没有正确的魔法方法,所以我得到了以下输出
10.0(m)
Traceback (most recent call last):
File "C:\Users\user\workspace\pineCar\src\sandBox.py", line 25, in <module>
B=diameter*2
TypeError: unsupported operand type(s) for *: 'instance' and 'int'
我想我可以重写每个魔法方法,让它们都返回self.value,但这样做感觉不太对。也许我需要一个装饰器?
另外,我知道我可以直接调用直径的值,但这样似乎有点重复。
3 个回答
0
在Python中,你可以重写很多不同的运算符,其中一些是用来模拟数字类型的。想了解更多,可以点击这里。
以乘法为例,你只需要像下面这样重写 __mul__(self, other)
:
def __mul__(self, other):
return self.value * other
你还可以重写其他数字运算,比如 __add__(self, other)
(用于加法)、__sub__(self, other)
等等。
稍微偏离一下话题,你可能还需要考虑,如果有人想把两个直径相乘或者把一个重量加到直径上,你希望它的行为是什么样的。
更新
根据你的评论,你可能更适合重写对象的浮点数表示,就像约翰提到的那样,虽然这没有重写数学运算符那么干净:
def __float__(self):
return self.value
0
class newVar():
def __init__(self,value=0.0,units='unknown'):
self.value=value
self.units=units
def __repr__(self):
return str(self.value) + '(' + self.units + ')'
def __mul__(self, other):
if hasattr(other, "value"):
return self.value * other.value
else:
return self.value * other
diameter=newVar(10.0,'m')
print diameter
print diameter*2
class newVar():
def __init__(self,value=0.0,units='unknown'):
self.value=value
self.units=units
def __repr__(self):
return str(self.value) + '(' + self.units + ')'
def __float__(self):
return self.value
diameter=newVar(10.0,'m')
print diameter
print float(diameter)*2
另一种可能的解决办法是重写对象的浮点数表示方式。
5
我曾经尝试自己实现类似的东西,但一直没能完成。有一种方法是从头开始创建一个新类,这个类同时包含数值和单位。不过,如果你想在计算中使用它,就必须实现一些特殊的方法,比如 __add__
和 __mul__
,这些方法负责处理加法和乘法运算。另一种方法是直接继承 float 类:
class FloatWithUnit(float):
def __new__(cls, val, unit):
return float.__new__(cls, val)
def __init__(self, val, unit):
self.unit = unit
def __str__(self):
return '%g %s' % (self, self.unit)
def __repr__(self):
return self.__str__()
继承 float 类显然有点棘手,所以除了 __init__
方法外,你还需要实现 __new__
方法,具体讨论可以参考 这里。当你在命令行输入这样的对象时,它会显示它的单位:
In [2]: g = FloatWithUnit(9.81, 'm/s^2')
In [3]: g
Out[3]: 9.81 m/s^2
In [4]: type(g)
Out[4]: __main__.FloatWithUnit
但是在计算时,它的表现就像一个普通的 float 一样。
In [5]: g2 = 2 * g
In [6]: g2
Out[6]: 19.62
In [7]: type(g2)
Out[7]: float