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

Joe*_*Joe 6 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
Run Code Online (Sandbox Code Playgroud)

它引发了一个异常:

AttributeError: 'Decimal' object has no attribute 'new_str'
Run Code Online (Sandbox Code Playgroud)

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

aba*_*ert 10

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

但你想要的是可行的.


NewDecimal(1) + NewDecimal(2)返回NewDecimal(3),您可以覆盖__add__:

def __add__(self, rhs):
    return NewDecimal(super().__add__(rhs))
Run Code Online (Sandbox Code Playgroud)

当然,你也想要覆盖__iadd__.并且不要忘记mul和所有其他数字特殊方法.

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

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


您可能需要阅读部分实施算术运算numbers模块文档,并执行fractions.Fraction(这是打算作为示例代码来创建新的数字类型,这就是为什么文档直接链接到源).你的生活比你的生活容易,Fraction因为你可以有效地回归Decimal每一个操作,然后转换(因为NewDecimal没有任何不同的数字行为Decimal),但值得看到所有的问题,并了解哪些是和不是相关的和为什么.