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( new value ) を呼び出すことにより、常に新しい Decimal オブジェクトを返します。
すべての演算を完全に再実装する以外に、これに対する回避策はありませんか?

4

2 に答える 2

10

別の方法で Decimal オブジェクトを出力するための追加のメソッドを用意するためだけに、実際にはこれを実行したくないでしょう。トップレベルの関数またはmonkeypatchedメソッドは、はるかにシンプルでクリーンです. または、代わりに、算術を委譲Moneyするメンバーを持つクラス。Decimal

しかし、あなたが望むことは実行可能です。


NewDecimal(1) + NewDecimal(2)returnを作成するにNewDecimal(3)は、単にオーバーライドできます__add__:

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

もちろん、オーバーライド__iadd__することもできます。mulそして、他のすべての数値特殊メソッドを忘れないでください。

しかし、それはまだ役に立ちませんDecimal(2) + NewDecimal(3)。それを機能させるには、定義する必要がありますNewDecimal.__radd__NewDecimal.__radd__また、 がの代わりに呼び出されるようにする必要がありDecimal.__add__ますが、継承を使用している場合は簡単です。Python にはこれを簡単にするための特別なルールがあるからです。

注:右側のオペランドの型が左側のオペランドの型のサブクラスであり、そのサブクラスが操作の反映されたメソッドを提供する場合、このメソッドは左側のオペランドの反映されていないメソッドの前に呼び出されます。この動作により、サブクラスは祖先の操作をオーバーライドできます。


モジュール ドキュメントの算術演算の実装セクション(新しい数値型を作成するためのサンプル コードとして機能することを意図したものであり、ドキュメントがソースに直接リンクしている理由です) の実装を読むことをお勧めします。すべての操作に対して に効果的にフォールバックしてから変換できるため (は と異なる数値動作を持たないため)、 の場合よりも簡単ですが、すべての問題を確認し、どれがそうでないかを理解する価値があります。関連性とその理由。numbersfractions.FractionFractionDecimalNewDecimalDecimal

于 2013-08-09T21:09:06.903 に答える