I'm creating a Money class, and I'd like to pass the object directly to the string format() function and get the money representation with 2 decimals and the currency symbol.
What method should I override to print with the string format function? Overriding str and repr did not work.
from decimal import Decimal
class Money(Decimal):
def __str__(self):
return "$" + format(self, ',.2f')
def __repr__(self):
return "$" + format(self, ',.2f')
m = Money("123.44")
print(m) # $123.44. Good.
m # $123.44. Good.
print("Amount: {0}".format(m)) # 123.44. Bad. I wanted $123.44
print(f"Amount: {m}") # 123.44. Bad. I wanted $123.44
You can give your class a __format__
method; in this case just call overridden version:
def __format__(self, spec):
spec = spec or ',.2f' # set a default spec when not explicitly given
return '$' + super().__format__(spec)
From the linked documentation:
Called by the
format()
built-in function, and by extension, evaluation of formatted string literals and thestr.format()
method, to produce a “formatted” string representation of an object. Theformat_spec
argument is a string that contains a description of the formatting options desired. The interpretation of theformat_spec
argument is up to the type implementing__format__()
, however most classes will either delegate formatting to one of the built-in types, or use a similar formatting option syntax.
You'll want to drop your __str__
and __repr__
implementations now, or at least not add another '$'
on top of the one __format__
now adds (which format(self, ...)
will trigger).
Demo:
>>> from decimal import Decimal
>>> class Money(Decimal):
... def __format__(self, spec):
... spec = spec or ',.2f' # set a default spec when not explicitly given
... return '$' + super().__format__(spec)
...
>>> m = Money("123.44")
>>> print("Amount: {0}".format(m))
Amount: $123.44
>>> print(f"Amount: {m}")
Amount: $123.44
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With