创建通常看起来像浮点数的类对象

时间:2014-04-19 17:31:27

标签: python magic-methods

我正在寻找能够跟踪变量单位的简单对象(也许我会添加其他属性,如公差)。以下是我到目前为止的情况:

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,但这似乎是重复的

3 个答案:

答案 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