import decimal class money(object): def __init__(self, amount="0"): try: if isinstance(amount, money): amount = amount.amount self.amount = decimal.Decimal(amount) except decimal.InvalidOperation: raise ValueError("amount value could not be converted to " "Decimal(): '{}'".format(amount)) def amount(self): return self.amount def __hash__(self): return hash(self.amount) def __repr__(self): return "{}".format(self.amount) def __str__(self): return self.__unicode__().encode('utf-8') def __unicode__(self): return u"${:,.2f}".format(self.amount) def __lt__(self, other): if not isinstance(other, money): other = money(other) return self.amount < other.amount def __le__(self, other): if not isinstance(other, money): other = money(other) return self.amount <= other.amount def __eq__(self, other): if isinstance(other, money): return self.amount == other.amount return False def __ne__(self, other): return not self == other def __gt__(self, other): if not isinstance(other, money): other = money(other) return self.amount > other.amount def __ge__(self, other): if not isinstance(other, money): other = money(other) return self.amount >= other.amount def __add__(self, other): if not isinstance(other, money): other = money(other) other = other.amount amount = self.amount + other return self.__class__(amount) def __radd__(self, other): return self.__add__(other) def __sub__(self, other): if not isinstance(other, money): other = money(other) other = other.amount amount = self.amount - other return self.__class__(amount) def __rsub__(self, other): return (-self).__add__(other) def __mul__(self, other): if isinstance(other, money): other = other.amount() amount = self.amount * decimal.Decimal(other) return self.__class__(amount) def __rmul__(self, other): return self.__mul__(other) def __div__(self, other): return self.__truediv__(other) def __truediv__(self, other): if isinstance(other, money): if other.amount == 0: raise ZeroDivisionError() return self.amount / other.amount else: if other == 0: raise ZeroDivisionError() amount = self.amount / decimal.Decimal(other) return self.__class__(amount) def __floordiv__(self, other): if isinstance(other, money): if other.amount == 0: raise ZeroDivisionError() return self.amount // other.amount else: if other == 0: raise ZeroDivisionError() amount = self.amount // other return self.__class__(amount) def __mod__(self, other): if isinstance(other, money): raise TypeError("modulo is unsupported between two '{}' " "objects".format(self.__class__.__name__)) if other == 0: raise ZeroDivisionError() amount = self.amount % other return self.__class__(amount) def __divmod__(self, other): if isinstance(other, money): if other.amount == 0: raise ZeroDivisionError() return divmod(self.amount, other.amount) else: if other == 0: raise ZeroDivisionError() whole, remainder = divmod(self.amount, other) return (self.__class__(whole), self.__class__(remainder)) def __pow__(self, other): if isinstance(other, money): raise TypeError("power operator is unsupported between two '{}' " "objects".format(self.__class__.__name__)) amount = self.amount ** other return self.__class__(amount) def __neg__(self): return self.__class__(-self.amount) def __pos__(self): return self.__class__(+self.amount) def __abs__(self): return self.__class__(abs(self.amount)) def __int__(self): return int(self.amount) def __float__(self): return float(self.amount) def __round__(self, ndigits=0): return self.__class__(round(self.amount, ndigits))