我想扩展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 )。 除了完全重新实现所有算术之外,有没有人没有解决方法?
答案 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