PythonMastery

Bank account class in Python

A BankAccount class with deposit and withdraw methods, a read-only balance, a transaction history and __repr__. Overdrafts are refused with a clear error.

A bank account is a good first class: it has data (the owner and the balance) and actions that change that data (deposit and withdraw). The class also checks every amount, so the balance can never go below zero.

The program

python
class BankAccount:
    def __init__(self, owner, opening_balance=0):
        self.owner = owner
        self._balance = 0
        self.history = []
        if opening_balance > 0:
            self.deposit(opening_balance)

    @property
    def balance(self):
        return self._balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit amount must be more than zero.")
        self._balance += amount
        self.history.append(("deposit", amount, self._balance))

    def withdraw(self, amount):
        if amount <= 0:
            raise ValueError("Withdrawal amount must be more than zero.")
        if amount > self._balance:
            raise ValueError(
                f"Cannot withdraw {amount:.2f}: the balance is only {self._balance:.2f}."
            )
        self._balance -= amount
        self.history.append(("withdraw", amount, self._balance))

    def __repr__(self):
        return f"BankAccount(owner={self.owner!r}, balance={self._balance:.2f})"


account = BankAccount("Ada", 100)
account.deposit(50)
account.withdraw(30)

try:
    account.withdraw(500)
except ValueError as error:
    print("Refused:", error)

print(account)
print(f"Balance: {account.balance:.2f}")

print("History:")
for kind, amount, balance_after in account.history:
    print(f"  {kind:<9}{amount:>8.2f}  balance {balance_after:.2f}")
output
Refused: Cannot withdraw 500.00: the balance is only 120.00.
BankAccount(owner='Ada', balance=120.00)
Balance: 120.00
History:
  deposit    100.00  balance 100.00
  deposit     50.00  balance 150.00
  withdraw    30.00  balance 120.00

How it works

For real money, use whole cents (10050 for 100.50) or the decimal module, because floats cannot store most decimal fractions exactly. 0.1 + 0.2 is 0.30000000000000004.

The custom exception program replaces the ValueError for overdrafts with an InsufficientFundsError that also carries the balance and the amount. The property decorator program explains @property in more detail.

Learn the idea: Object-Oriented Programming, Errors & Exceptions: When Things Go Wrong