Coding problem · Medium · Language Idioms

Immutable Money Value Object (dataclasses)

Medium Language practicals Seen at Stripe, Wise, Revolut

Create a value object Money with a @dataclass:

  • fields amount_cents: int and currency: str;
  • immutable — assigning to a field raises dataclasses.FrozenInstanceError;
  • Money + Money returns a new Money; adding different currencies raises ValueError;
  • str(Money(1999, "USD")) → "19.99 USD" (also negative: "-5.00 EUR");
  • instances sort by amount_cents, then currency.

Hints

Hint 1

@dataclass(frozen=True, order=True) gives immutability, __eq__, __hash__ and ordering by field order.

Hint 2

Format with divmod(abs(cents), 100) and add the sign back.

Write and run your solution

Loading the editor… (JavaScript is required to run code in your browser.)

Solution and explanation

Show the solution

Time O(1) · Space O(1)

frozen=True makes instances immutable and hashable (safe as dict keys and in sets); order=True generates comparison methods using field order — here amount, then currency. Value objects like Money are compared by value, never by identity. Returning NotImplemented from __add__ for unknown types lets Python try the other operand and produce a proper TypeError.

Reference solution

from dataclasses import dataclass


@dataclass(frozen=True, order=True)
class Money:
    amount_cents: int
    currency: str

    def __add__(self, other: "Money") -> "Money":
        if not isinstance(other, Money):
            return NotImplemented
        if other.currency != self.currency:
            raise ValueError(f"cannot add {other.currency} to {self.currency}")
        return Money(self.amount_cents + other.amount_cents, self.currency)

    def __str__(self) -> str:
        units, cents = divmod(abs(self.amount_cents), 100)
        sign = "-" if self.amount_cents < 0 else ""
        return f"{sign}{units}.{cents:02d} {self.currency}"

Common mistakes

  • Floats for money.
  • Mutable value objects used as dict keys.
  • Formatting negatives as -0.-5.

Follow-up questions

  • Add __mul__ for quantities and allocation without losing cents.
  • Use Decimal for currencies with 3 decimal places.