我正在寻找能够跟踪变量单位的简单对象(也许我会添加其他属性,如公差)。以下是我到目前为止的情况:
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但听起来不对。也许我需要装饰师?
另外,我知道我可以直接调用diameter.value,但这似乎是重复的
答案 0 :(得分:5)
我曾尝试自己实现类似的东西,但从未设法完成它。一种方法是从头开始实现一个新类,它包含值和单位。但是如果你想在计算中使用它,你必须实现所有神奇的方法,如__add__
和__mul__
。另一种方法是子类浮动本身:
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__()
子类化浮点显然有点棘手,因此除了__new__
之外,您还必须实现__init__
,有关详细讨论,请参阅here。在命令行中输入这样的对象时,它会显示其单位:
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
但是当用于caluations时,它的行为就像普通的浮动
In [5]: g2 = 2 * g
In [6]: g2
Out[6]: 19.62
In [7]: type(g2)
Out[7]: float
答案 1 :(得分:0)
在Python中,您可以覆盖许多不同的运算符,其中一些运算符用于模拟数字类型。您可以找到更多here。
在乘法的情况下,您需要做的就是覆盖__mul__(self, other)
,如下所示:
def __mul__(self, other):
return self.value * other
您还可以覆盖其他数字操作,例如__add__(self, other)
(用于添加),__sub__(self, other)
等。
在某种程度上不相关的说明中,您可能还想考虑一下,如果想要将直径相乘或增加直径的权重,您希望行为是什么。
<强>更新强>
根据你的评论,你可能最好覆盖John提到的对象浮点表示,尽管它不像覆盖数学运算符那样干净:
def __float__(self):
return self.value
答案 2 :(得分: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