From c52ca3253840635a7f3dbe26254ec788346ad7a1 Mon Sep 17 00:00:00 2001 From: malikabaguari Date: Sat, 27 Jun 2026 02:18:29 +0200 Subject: [PATCH] Week3_ Lab | Object Oriented Programming. solution of the additionnal exercises of Lab | Object Oriented Programming. --- lab-python-oop.ipynb (1).ipynb | 161 +++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 lab-python-oop.ipynb (1).ipynb diff --git a/lab-python-oop.ipynb (1).ipynb b/lab-python-oop.ipynb (1).ipynb new file mode 100644 index 0000000..3ada5fb --- /dev/null +++ b/lab-python-oop.ipynb (1).ipynb @@ -0,0 +1,161 @@ +{ + "metadata": { + "kernelspec": { + "name": "python", + "display_name": "Python (Pyodide)", + "language": "python" + }, + "language_info": { + "codemirror_mode": { + "name": "python", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8" + } + }, + "nbformat_minor": 5, + "nbformat": 4, + "cells": [ + { + "id": "cdcc1d61-3e4b-485c-97b2-813c6aa2e03b", + "cell_type": "code", + "source": "#lab-python-oop.ipynb", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": null + }, + { + "id": "86c429de-ba3b-42d3-b0ea-7c20b54c0da5", + "cell_type": "markdown", + "source": "Create a BankAccount class with the following attributes and methods:\n\nAttributes:\n\naccount_number (a unique identifier for the bank account)\nbalance (the current balance of the account. By default, is 0)\nMethods:\n\ndeposit(amount) - adds the specified amount to the account balance\nwithdraw(amount) - subtracts the specified amount from the account balance\nget_balance() - returns the current balance of the account\nget_account_number() - returns the account number of the account\nInstructions:\n\nCreate a BankAccount class with the above attributes and methods.\nTest the class by creating a few instances of BankAccount and making deposits and withdrawals.\nEnsure that the account_number attribute is unique for each instance of BankAccount.\nHint: create a class attribute account_count. The account_count class attribute is used to keep track of the total number of bank accounts that have been created using the BankAccount class. Every time a new BankAccount object is created, the account_count attribute is incremented by one. This can be useful for various purposes, such as generating unique account numbers or monitoring the growth of a bank's customer base.", + "metadata": {} + }, + { + "id": "eed5880d-192b-4d8b-88d2-40f610dcd8b8", + "cell_type": "code", + "source": "class BankAccount:\n account_count = 0 # class attribute shared by ALL accounts\n\n def __init__(self, balance=0):\n # Each time a new account is created, increase the global counter\n BankAccount.account_count += 1\n\n # Assign a unique account number based on creation order\n self.account_number = BankAccount.account_count\n\n # Store the initial balance for this specific account\n self.balance = balance\n\n def deposit(self, amount):\n # Add money to the account\n if amount > 0:\n self.balance += amount\n\n def withdraw(self, amount):\n # Only allow withdrawal if enough money exists\n if amount <= self.balance:\n self.balance -= amount\n else:\n print(\"Insufficient balance\")\n\n def get_balance(self):\n # Return current balance (encapsulation principle)\n return self.balance\n\n def get_account_number(self):\n # Return account identifier (encapsulation)\n return self.account_number", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": 2 + }, + { + "id": "08cd62e9-7cf5-4d3e-8cf7-d0db1187f698", + "cell_type": "code", + "source": "# now we test our code", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": null + }, + { + "id": "864a310d-6485-4d79-8172-d9a7ecafa5c0", + "cell_type": "code", + "source": "account1 = BankAccount(1000)\naccount2 = BankAccount(500)\n\nprint(\"Account 1 balance:\", account1.get_balance())\nprint(\"Account 1 number:\", account1.get_account_number())\n\nprint(\"Account 2 balance:\", account2.get_balance())\nprint(\"Account 2 number:\", account2.get_account_number())\n\naccount1.deposit(500)\naccount1.withdraw(200)\nprint(\"Account 1 balance after transactions:\", account1.get_balance())\n\naccount2.withdraw(600)\nprint(\"Account 2 balance after transactions:\", account2.get_balance())", + "metadata": { + "trusted": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "Account 1 balance: 1000\nAccount 1 number: 1\nAccount 2 balance: 500\nAccount 2 number: 2\nAccount 1 balance after transactions: 1300\nInsufficient balance\nAccount 2 balance after transactions: 500\n" + } + ], + "execution_count": 3 + }, + { + "id": "4d0082cf-9a18-4ba9-99e0-23c49ed08c23", + "cell_type": "code", + "source": "#Challenge 2 — SavingsAccount (Inheritance)", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": null + }, + { + "id": "507a64af-30d9-4dc0-93dd-95878c7fbf06", + "cell_type": "markdown", + "source": "# Create a SavingsAccount class that inherits from the BankAccount class. The SavingsAccount class should have the following additional attributes and methods:\nBecause a savings account is a bank account with extra features.\nWe reuse:\nbalance\ndeposit\nwithdraw\naccount number logic\n\nwe use : super().__init__(balance) in order to avoid rewriting BankAccount logic, keeps code DRY (Don’t Repeat ourselves), and ensures proper initialization\n\nthe interest logic : self.balance += self.balance * self.interest_rate = This simulates real banking:\ninterest is proportional to current balance\ngrowth is percentage-based", + "metadata": {} + }, + { + "id": "294b2e3d-2db7-4818-94c0-e8698cf659c4", + "cell_type": "code", + "source": "class SavingsAccount(BankAccount):\n\n def __init__(self, balance=0, interest_rate=0.01):\n # Reuse parent constructor\n super().__init__(balance)\n\n # Add specific attribute for savings account\n self.interest_rate = interest_rate\n\n def add_interest(self):\n # Apply interest to current balance\n self.balance += self.balance * self.interest_rate\n\n def get_interest_rate(self):\n return self.interest_rate", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": 5 + }, + { + "id": "34088e19-20bf-4c16-b80b-72e047724e97", + "cell_type": "code", + "source": "savings = SavingsAccount(100, 0.02)\n\nsavings.deposit(50)\nsavings.withdraw(25)\nsavings.add_interest()\n\nprint(\"Current balance:\", savings.get_balance())\nprint(\"Interest rate:\", savings.get_interest_rate())", + "metadata": { + "trusted": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "Current balance: 127.5\nInterest rate: 0.02\n" + } + ], + "execution_count": 6 + }, + { + "id": "5925d2fd-19c2-4ad6-852e-bfd1f77ef878", + "cell_type": "code", + "source": "# Challenge 3 — CheckingAccount (Override + fees)", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": null + }, + { + "id": "53b21074-d0a5-4fec-879b-c1e8d57236df", + "cell_type": "code", + "source": "class CheckingAccount(BankAccount):\n\n def __init__(self, balance=0, transaction_fee=1):\n super().__init__(balance)\n self.transaction_fee = transaction_fee\n self.transaction_count = 0\n\n # Override deposit\n def deposit(self, amount):\n super().deposit(amount)\n self.transaction_count += 1\n\n # Override withdraw\n def withdraw(self, amount):\n if amount <= self.balance:\n super().withdraw(amount)\n self.transaction_count += 1\n else:\n print(\"Insufficient balance\")\n\n def deduct_fees(self):\n total_fees = self.transaction_count * self.transaction_fee\n\n if self.balance >= total_fees:\n self.balance -= total_fees\n print(f\"Transaction fees of {total_fees}$ have been deducted from your account balance.\")\n else:\n print(\"Insufficient balance to deduct fees\")\n\n self.transaction_count = 0\n\n def reset_transactions(self):\n self.transaction_count = 0\n\n def get_transaction_count(self):\n return self.transaction_count", + "metadata": { + "trusted": true + }, + "outputs": [], + "execution_count": 7 + }, + { + "id": "a9f9bc15-50b5-49c5-8379-e2c7c403a022", + "cell_type": "code", + "source": "checking = CheckingAccount(500, 2)\n\nchecking.deposit(100)\nchecking.withdraw(50)\nchecking.deduct_fees()\n\nprint(\"Current balance:\", checking.get_balance())\nprint(\"Transaction count:\", checking.get_transaction_count())\n\nchecking.deposit(200)\nchecking.withdraw(75)\nchecking.deduct_fees()\n\nprint(\"Current balance:\", checking.get_balance())\nprint(\"Transaction count:\", checking.get_transaction_count())", + "metadata": { + "trusted": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": "Transaction fees of 4$ have been deducted from your account balance.\nCurrent balance: 546\nTransaction count: 0\nTransaction fees of 4$ have been deducted from your account balance.\nCurrent balance: 667\nTransaction count: 0\n" + } + ], + "execution_count": 8 + }, + { + "id": "b09bf873-c2cd-492d-a68d-afcbc52ad307", + "cell_type": "markdown", + "source": "Override deposit and withdraw → to add transaction tracking\nsuper() → reuse existing logic without duplication\ntransaction_count → tracks number of operations for fee calculation\ndeduct_fees() → simulates real banking monthly fees system\nreset → prepares account for next billing cycle\n", + "metadata": {} + } + ] +} \ No newline at end of file