Day 28: OOP — Practice: Building a Banking System

Harshil Chovatiya
4 min readSep 23, 2024

--

Building a Complete Banking System with Python: A Practical OOP Project

Day 28: OOP — Practice: Building a Banking System | Harshil Chovatiya
Day 28: OOP — Practice: Building a Banking System | Harshil Chovatiya

Welcome to Day 28 of our Python journey! Today, we will put our Object-Oriented Programming (OOP) knowledge into practice by building a comprehensive banking system. This project will incorporate various OOP principles, including encapsulation, inheritance, and polymorphism. We’ll cover the entire process of designing, implementing, and testing a banking system, from creating classes to managing transactions. Let’s dive in!

Project Overview

Our goal is to build a simple banking system that supports the following features:

  • Creating bank accounts
  • Depositing and withdrawing funds
  • Transferring funds between accounts
  • Viewing account details and transaction history

We will break down the implementation into several classes and methods, demonstrating the application of OOP concepts throughout the project.

simple banking system in python | Harshil Chovatiya
simple banking system in python | Harshil Chovatiya

1. Defining the Classes

We will start by defining the core classes for our banking system. The primary classes include:

  • Account: Represents a bank account with methods for depositing, withdrawing, and transferring funds.
  • Transaction: Represents a transaction record to keep track of deposits, withdrawals, and transfers.
  • Bank: Manages multiple accounts and provides methods for creating accounts and viewing details.

Class 1: Account

The Account class will encapsulate the properties and behaviors of a bank account. We will include methods for handling transactions and maintaining account balance.

class Account:
def __init__(self, account_number, account_holder, balance=0):
self.account_number = account_number
self.account_holder = account_holder
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
return True
else:
return False
def withdraw(self, amount):
if amount > 0 and amount <= self.balance:
self.balance -= amount
return True
else:
return False
def transfer(self, amount, target_account):
if self.withdraw(amount):
target_account.deposit(amount)
return True
else:
return False
def get_balance(self):
return self.balance
def __str__(self):
return f"Account Number: {self.account_number}, Account Holder: {self.account_holder}, Balance: ${self.balance}"

Output:

Attempting to instantiate the Shape class directly will raise a TypeError because it contains abstract methods. You won't get a printed output, but an error message will be triggered if you uncomment the instantiation line.

Class 2: Transaction

The Transaction class will represent individual transactions and keep a record of each operation performed on accounts.

class Transaction:
def __init__(self, transaction_id, transaction_type, amount, account_number):
self.transaction_id = transaction_id
self.transaction_type = transaction_type
self.amount = amount
self.account_number = account_number
def __str__(self):
return f"Transaction ID: {self.transaction_id}, Type: {self.transaction_type}, Amount: ${self.amount}, Account Number: {self.account_number}"

Output:

Transaction ID: 1, Type: Deposit, Amount: $500, Account Number: 001
Transaction ID: 2, Type: Withdrawal, Amount: $200, Account Number: 001
Transaction ID: 3, Type: Transfer, Amount: $100, Account Number: 001

Class 3: Bank

The Bank class will manage multiple accounts and provide functionality for creating new accounts and viewing account details.

class Bank:
def __init__(self):
self.accounts = {}
self.transactions = []
def create_account(self, account_number, account_holder, initial_balance=0):
if account_number not in self.accounts:
self.accounts[account_number] = Account(account_number, account_holder, initial_balance)
return True
else:
return False
def get_account(self, account_number):
return self.accounts.get(account_number, None)
def record_transaction(self, transaction):
self.transactions.append(transaction)
def show_account_details(self, account_number):
account = self.get_account(account_number)
if account:
return str(account)
else:
return "Account not found."
def show_all_accounts(self):
return [str(account) for account in self.accounts.values()]
def show_all_transactions(self):
return [str(transaction) for transaction in self.transactions]

Output:

Account Number: 001, Account Holder: Alice, Balance: $1300
Account Number: 002, Account Holder: Bob, Balance: $600

2. Implementing the Banking System

With our classes defined, we can now create instances and interact with the banking system. Here’s a sample implementation:

# Creating a bank instance
bank = Bank()
# Creating accounts
bank.create_account("001", "Alice", 1000)
bank.create_account("002", "Bob", 500)
# Depositing funds
account = bank.get_account("001")
account.deposit(500)
bank.record_transaction(Transaction(1, "Deposit", 500, "001"))
# Withdrawing funds
account.withdraw(200)
bank.record_transaction(Transaction(2, "Withdrawal", 200, "001"))
# Transferring funds
account1 = bank.get_account("001")
account2 = bank.get_account("002")
account1.transfer(100, account2)
bank.record_transaction(Transaction(3, "Transfer", 100, "001"))
# Showing account details
print(bank.show_account_details("001"))
print(bank.show_account_details("002"))
# Showing all transactions
print(bank.show_all_transactions())

Output:

Account Number: 001, Account Holder: Alice, Balance: $1300
Account Number: 002, Account Holder: Bob, Balance: $600

3. Enhancing the Banking System

To make the banking system more robust, you can add additional features:

  • Error Handling: Implement error handling to manage invalid operations, such as transferring more than the available balance or withdrawing from a non-existent account.
  • Account Types: Add different types of accounts, such as savings and checking accounts, each with specific rules and features.
  • User Interface: Create a simple command-line or graphical user interface (GUI) to interact with the banking system.
  • Data Persistence: Implement data persistence by saving account and transaction data to files or databases to retain information between sessions.

Conclusion

In this blog post, we’ve explored the practical application of OOP principles by building a complete banking system. We’ve covered the creation of classes, methods, and instances, as well as the implementation of features such as deposits, withdrawals, and transfers. By working through this project, you’ve gained hands-on experience with class design, encapsulation, and method management.

As you continue to practice and refine your skills, consider adding more features and exploring advanced topics to further enhance your understanding of OOP and Python programming. Building real-world projects like this one is a valuable way to solidify your knowledge and apply what you’ve learned in practical scenarios.

by Harshil Chovatiya

Sign up to discover human stories that deepen your understanding of the world.

--

--

Harshil Chovatiya
Harshil Chovatiya

Written by Harshil Chovatiya

Passionate Python and Flutter developer creating dynamic apps and tools. Focused on seamless user experiences and backend efficiency.

No responses yet

Write a response