Python,如何扩展Decimal类以添加有用的方法

时间:2013-08-09 19:55:38

标签: python python-2.7

我想扩展Decimal类,为它添加一些有用的方法,特别是为了处理钱。

我去的时候出现的问题:

from decimal import Decimal
class NewDecimal(Decimal):
    def new_str(self):
        return "${}".format(self)

d1 = NewDecimal(1)
print d1.new_str() # prints '$1'

d2 = NewDecimal(2)
d3 = NewDecimal(3)
d5 = d2 + d3
print d5.new_str()   #exception happens here

它抛出异常:

AttributeError: 'Decimal' object has no attribute 'new_str'

这是因为Decimal进行算术的方式,它总是返回一个新的Decimal对象,通过在计算结束时字面上调用Decimal( new value )。 除了完全重新实现所有算术之外,有没有人没有解决方法?

2 个答案:

答案 0 :(得分:8)

您可能实际上并不想这样做,只是为了有一个额外的方法以另一种方式打印Decimal对象。顶级函数或monkeypatched方法更简单,更清晰。或者,或者,Money类具有Decimal成员,它将算术委托给。

但你想要的是可行的。


NewDecimal(1) + NewDecimal(2)返回NewDecimal(3),您只需覆盖__add__

def __add__(self, rhs):
    return NewDecimal(super().__add__(rhs))

当然,您也希望覆盖__iadd__。不要忘记mul和所有其他numeric special methods

但这对Decimal(2) + NewDecimal(3)仍无济于事。要做到这一点,您需要定义NewDecimal.__radd__。您还需要确保调用NewDecimal.__radd__而不是Decimal.__add__,但是当您使用继承时,这很容易,因为Python有专门的规则来简化:

  

注意:如果右操作数的类型是左操作数类型的子类,并且该子类提供了操作的反射方法,则此方法将在左操作数的非反射方法之前调用。此行为允许子类覆盖其祖先的操作。


您可能需要阅读numbers模块文档中的Implementing the arithmetic operations部分和the implementation of fractions.Fraction部分(其用作创建新数字类型的示例代码),这就是为什么docs直接链接到源)。你的生活比Fraction更容易,因为你可以有效地回退到每个操作的Decimal然后转换(因为NewDecimal没有Decimal的任何不同的数字行为}),但值得看看所有问题,并了解哪些是相关的,哪些是不相关的,为什么。

答案 1 :(得分:1)

快速找到你想要的东西,就像这样:

from decimal import Decimal
class NewDecimal(Decimal):
    def __str__(self):  
        return "${}".format(self)

    def __add__(self,b):
        return NewDecimal( Decimal.__add__(self,b) )


d1 = NewDecimal(1)
print d1 # prints '$1'

d2 = NewDecimal(2)
d3 = NewDecimal(3)
d5 = d2 + d3
print d5

> $5