Je souhaite utiliser la classe Decimal dans mon programme Python pour effectuer des calculs financiers. Les décimales ne fonctionnent pas avec les flottants - ils nécessitent d'abord une conversion explicite en chaînes. J'ai donc décidé de sous-classer Decimal pour pouvoir travailler avec des flottants sans conversions explicites.Sous-classe Decimal en Python
m_Decimal.py:
# -*- coding: utf-8 -*-
import decimal
Decimal = decimal.Decimal
def floatCheck (obj) : # usually Decimal does not work with floats
return repr (obj) if isinstance (obj, float) else obj # this automatically converts floats to Decimal
class m_Decimal (Decimal) :
__integral = Decimal (1)
def __new__ (cls, value = 0) :
return Decimal.__new__ (cls, floatCheck (value))
def __str__ (self) :
return str (self.quantize (self.__integral) if self == self.to_integral() else self.normalize()) # http://docs.python.org/library/decimal.html#decimal-faq
def __mul__ (self, other) :
print (type(other))
Decimal.__mul__ (self, other)
D = m_Decimal
print (D(5000000)*D(2.2))
Alors maintenant, au lieu d'écrire D(5000000)*D(2.2)
je devrais pouvoir écrire D(5000000)*2.2
sans lainage exceptions.
J'ai plusieurs questions:
Est-ce que ma décision me causer des ennuis?
Réimplémenter
__mul__
ne fonctionne pas en cas deD(5000000)*D(2.2)
, parce que l'autre argument est de typeclass '__main__.m_Decimal'
, mais vous pouvez voir dans le module décimal ceci:
decimal.py, ligne 5292:
def _convert_other(other, raiseit=False):
"""Convert other to Decimal.
Verifies that it's ok to use in an implicit construction.
"""
if isinstance(other, Decimal):
return other
if isinstance(other, (int, long)):
return Decimal(other)
if raiseit:
raise TypeError("Unable to convert %s to Decimal" % other)
return NotImplemented
Le module décimal s'attend à ce que l'argument soit Decimal ou int. Cela signifie que je devrais d'abord convertir mon objet m_Decimal en chaîne, puis en décimal. Mais c'est beaucoup de gaspillage - m_Decimal est descendant de Decimal - comment puis-je l'utiliser pour rendre la classe plus rapide (Decimal est déjà très lent).
- Lorsque cDecimal apparaîtra, ce sous-classement fonctionnera-t-il?
Gardez à l'esprit que la multiplication d'un décimal par un flotteur rend une décimale réduite précision, ce qui explique pourquoi cette opération n'est pas mis en œuvre en premier lieu. –
Vous ne savez pas pourquoi vous devriez convertir? 'isinstance' prend correctement en compte le sous-classement ...' isinstance (d, m_Decimal) 'implique' isinstance (d, Decimal) '. – Dirk
Votre opération va sûrement causer des problèmes avec le but des décimales. Ne les utilisez pas si vous n'en avez pas besoin ou si vous ne comprenez pas leur raison d'être; Je vous recommande de vérifier la norme IEEE 754. –