I want to learn only Python programming from scratch in 7 days.My goal is to go from complete beginner to job-ready level, with a strong understanding of both theory and practical coding.Please give me a clear and structured 7-day learning plan that includes both explanations and real coding practice.✅ INSTRUCTIONS:Duration: 7 daysDaily effort: 6 hours per dayDo not include time slots (like 9 AM to 1 PM)Provide the plan directly in chat (no ZIP files or external tools)Each day should have only 3 real coding exercises✅ EACH DAY SHOULD FOLLOW THIS TEMPLATE STRUCTURE:1. 📘 THEORY / INTRODUCTIONWhat is the topic?How it works? (Logic or concept)Syntax / structure (with Python code examples)2. ❗ WHY IT'S IMPORTANTReal-world useRole in Python projects or automationUsage in jobs and interviews3. 🔑 KEY CONCEPTSMain terms or logicKey functions or commandsBest practices or common patterns4. 🧪 PRACTICAL EXERCISESOnly 3 real coding exercises per dayBeginner to intermediate levelMust help build logic and confidence5. 💡 TIPS OR NOTESCommon mistakes to avoidShortcuts or tricksTips from real interview experience6. 🔁 REVISION / MINI QUIZ (Optional)3–5 MCQs or true/falseQuick recall of the day’s learning7. 📂 RESOURCES / REFERENCESOnly Hindi YouTube videosMust be beginner-friendly and easy to followNo English videos, no tool recommendations📌 TOPICS TO COVER:Day 1: Introduction to Python, Syntax, Variables, Data TypesDay 2: Conditional Statements & LoopsDay 3: Functions and ModulesDay 4: Data Structures in Python (List, Tuple, Set, Dictionary)Day 5: File Handling & Exception HandlingDay 6: Object-Oriented Programming (OOP) in PythonDay 7: Mini Projects + Interview Coding Practice (with Recap)✅ Please deliver the complete plan directly in chat following the structure above.✅ Focus on clarity, practice, and job preparation.✅ All videos must be in Hindi and beginner-friendly.
From Complete Beginner to Job-Ready Level
What is Python? Python is a high-level, interpreted programming language known for its simple syntax and readability. It's like writing instructions in plain English that computers can understand.
How it works?
Python code is executed line by line by the Python interpreter. You write code in .py
files and run them using the python
command.
Syntax & Structure:
# This is a comment
print("Hello, World!") # Output: Hello, World!
# Variables - containers to store data
name = "Rahul"
age = 25
height = 5.8
is_student = True
# Data Types
text = "Hello" # String (str)
number = 42 # Integer (int)
decimal = 3.14 # Float (float)
flag = True # Boolean (bool)
# Checking data types
print(type(name)) # <class 'str'>
print(type(age)) # <class 'int'>
Real-world use:
Role in Python projects: Variables and data types are the foundation of every program. Without understanding these, you can't store or manipulate information.
Usage in jobs:
Main terms:
=
Key functions:
type() # Check data type
str() # Convert to string
int() # Convert to integer
float() # Convert to decimal
bool() # Convert to boolean
Best practices:
student_name
not sn
my_variable
not myVariable
Exercise 1: Personal Information Storage
# Create variables for your personal info
first_name = "Your Name"
last_name = "Your Surname"
age = 20
height_in_feet = 5.6
is_employed = False
# Print formatted information
print("Name:", first_name, last_name)
print("Age:", age, "years")
print("Height:", height_in_feet, "feet")
print("Employed:", is_employed)
Exercise 2: Simple Calculator
# Take two numbers and perform basic operations
num1 = 15
num2 = 4
addition = num1 + num2
subtraction = num1 - num2
multiplication = num1 * num2
division = num1 / num2
print("Addition:", addition)
print("Subtraction:", subtraction)
print("Multiplication:", multiplication)
print("Division:", division)
Exercise 3: Data Type Conversion
# Convert between different data types
text_number = "123"
decimal_text = "45.67"
number = 100
# Convert and display
converted_int = int(text_number)
converted_float = float(decimal_text)
converted_string = str(number)
print("Original:", text_number, "Type:", type(text_number))
print("Converted:", converted_int, "Type:", type(converted_int))
print("Float conversion:", converted_float)
print("String conversion:", converted_string)
Common mistakes:
print
, int
)=
(assignment) with ==
(comparison)Shortcuts:
print(f"Name: {name}")
for formatted stringsa, b, c = 1, 2, 3
a, b = b, a
Interview tips:
3.14
?
a) int b) float c) strtype()
function return?
a) Value of variable b) Data type c) Memory addressAnswers: 1-b, 2-b, 3-False, 4-b, 5-b
Hindi YouTube Videos:
What are Conditional Statements? Conditional statements allow your program to make decisions based on certain conditions. It's like asking "if this is true, do this, otherwise do that."
What are Loops? Loops allow you to repeat code multiple times without writing it again and again.
Syntax & Structure:
# If-elif-else statements
age = 18
if age >= 18:
print("You can vote")
elif age >= 16:
print("You can get a learner's license")
else:
print("You are too young")
# For loop
for i in range(5):
print("Number:", i)
# While loop
count = 0
while count < 3:
print("Count:", count)
count += 1
# Loop with lists
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
print("Fruit:", fruit)
Real-world use:
Role in Python projects:
Usage in jobs:
Main terms:
Key operators:
# Comparison operators
== # Equal to
!= # Not equal to
> # Greater than
< # Less than
>= # Greater than or equal
<= # Less than or equal
# Logical operators
and # Both conditions must be true
or # At least one condition must be true
not # Opposite of the condition
Best practices:
break
and continue
wiselyExercise 1: Grade Calculator
# Calculate grade based on marks
marks = 85
if marks >= 90:
grade = "A+"
elif marks >= 80:
grade = "A"
elif marks >= 70:
grade = "B"
elif marks >= 60:
grade = "C"
elif marks >= 50:
grade = "D"
else:
grade = "F"
print(f"Marks: {marks}")
print(f"Grade: {grade}")
# Additional condition
if marks >= 50:
print("Result: PASS")
else:
print("Result: FAIL")
Exercise 2: Number Pattern Generator
# Generate different patterns using loops
# Pattern 1: Numbers 1 to 10
print("Pattern 1:")
for i in range(1, 11):
print(i, end=" ")
print()
# Pattern 2: Even numbers
print("\nPattern 2 - Even numbers:")
for i in range(2, 21, 2):
print(i, end=" ")
print()
# Pattern 3: Multiplication table
print("\nPattern 3 - Table of 5:")
for i in range(1, 11):
result = 5 * i
print(f"5 x {i} = {result}")
Exercise 3: Simple Number Guessing Game
# Number guessing game with while loop
secret_number = 7
attempts = 0
max_attempts = 3
print("Guess the number between 1 and 10!")
while attempts < max_attempts:
guess = int(input("Enter your guess: "))
attempts += 1
if guess == secret_number:
print(f"Congratulations! You guessed it in {attempts} attempts!")
break
elif guess < secret_number:
print("Too low!")
else:
print("Too high!")
if attempts == max_attempts:
print(f"Game over! The number was {secret_number}")
Common mistakes:
:
after if/for/while statementsShortcuts:
range(start, stop, step)
for custom sequencesif 18 <= age <= 65:
enumerate()
for index and value: for i, item in enumerate(list):
Interview tips:
break
statement exits only the current iteration.range(2, 10, 2)
generate?
a) 2,4,6,8 b) 2,4,6,8,10 c) 2,3,4,5,6,7,8,9Answers: 1-b, 2-b, 3-False, 4-a, 5-b
Hindi YouTube Videos:
What are Functions? Functions are reusable blocks of code that perform specific tasks. Think of them as mini-programs within your main program that you can call whenever needed.
What are Modules? Modules are files containing Python code that can be imported and used in other programs. They help organize code and avoid repetition.
Syntax & Structure:
# Basic function
def greet():
print("Hello, World!")
# Function with parameters
def greet_person(name):
print(f"Hello, {name}!")
# Function with return value
def add_numbers(a, b):
result = a + b
return result
# Function with default parameters
def introduce(name, age=25):
return f"My name is {name} and I am {age} years old"
# Calling functions
greet()
greet_person("Rahul")
sum_result = add_numbers(5, 3)
print(sum_result)
# Importing modules
import math
import random
from datetime import datetime
# Using module functions
print(math.sqrt(16)) # 4.0
print(random.randint(1, 10)) # Random number between 1-10
print(datetime.now()) # Current date and time
Real-world use:
Role in Python projects:
Usage in jobs:
Main terms:
def
Key concepts:
# Scope - where variables can be accessed
global_var = "I'm global"
def my_function():
local_var = "I'm local"
print(global_var) # Can access global
print(local_var) # Can access local
# Lambda functions (one-line functions)
square = lambda x: x * x
print(square(5)) # 25
# Multiple return values
def get_name_age():
return "John", 25
name, age = get_name_age()
Best practices:
Exercise 1: Calculator with Functions
# Create a calculator using functions
def add(x, y):
"""Add two numbers"""
return x + y
def subtract(x, y):
"""Subtract two numbers"""
return x - y
def multiply(x, y):
"""Multiply two numbers"""
return x * y
def divide(x, y):
"""Divide two numbers"""
if y != 0:
return x / y
else:
return "Cannot divide by zero!"
def calculator():
"""Main calculator function"""
print("Simple Calculator")
print("1. Add")
print("2. Subtract")
print("3. Multiply")
print("4. Divide")
choice = input("Enter choice (1/2/3/4): ")
num1 = float(input("Enter first number: "))
num2 = float(input("Enter second number: "))
if choice == '1':
result = add(num1, num2)
print(f"{num1} + {num2} = {result}")
elif choice == '2':
result = subtract(num1, num2)
print(f"{num1} - {num2} = {result}")
elif choice == '3':
result = multiply(num1, num2)
print(f"{num1} * {num2} = {result}")
elif choice == '4':
result = divide(num1, num2)
print(f"{num1} / {num2} = {result}")
else:
print("Invalid choice!")
# Run calculator
calculator()
Exercise 2: Password Generator using Modules
# Password generator using random module
import random
import string
def generate_password(length=8, include_symbols=True):
"""Generate a random password"""
# Define character sets
letters = string.ascii_letters # a-z, A-Z
digits = string.digits # 0-9
symbols = "!@#$%^&*"
# Create character pool
char_pool = letters + digits
if include_symbols:
char_pool += symbols
# Generate password
password = ""
for i in range(length):
password += random.choice(char_pool)
return password
def check_password_strength(password):
"""Check password strength"""
score = 0
feedback = []
if len(password) >= 8:
score += 1
else:
feedback.append("Password should be at least 8 characters")
if any(c.isupper() for c in password):
score += 1
else:
feedback.append("Add uppercase letters")
if any(c.islower() for c in password):
score += 1
else:
feedback.append("Add lowercase letters")
if any(c.isdigit() for c in password):
score += 1
else:
feedback.append("Add numbers")
if any(c in "!@#$%^&*" for c in password):
score += 1
else:
feedback.append("Add special characters")
strength_levels = ["Very Weak", "Weak", "Fair", "Good", "Strong"]
strength = strength_levels[min(score, 4)]
return strength, feedback
# Test the functions
new_password = generate_password(12, True)
print(f"Generated Password: {new_password}")
strength, tips = check_password_strength(new_password)
print(f"Password Strength: {strength}")
if tips:
print("Suggestions:", ", ".join(tips))
Exercise 3: Student Management System
# Student management system using functions
import datetime
def add_student(students_dict, name, age, grade):
"""Add a new student"""
student_id = len(students_dict) + 1
students_dict[student_id] = {
'name': name,
'age': age,
'grade': grade,
'added_date': datetime.datetime.now().strftime("%Y-%m-%d")
}
return f"Student {name} added successfully with ID: {student_id}"
def display_student(students_dict, student_id):
"""Display student information"""
if student_id in students_dict:
student = students_dict[student_id]
return f"""
Student ID: {student_id}
Name: {student['name']}
Age: {student['age']}
Grade: {student['grade']}
Added Date: {student['added_date']}
"""
else:
return "Student not found!"
def calculate_class_average(students_dict):
"""Calculate average grade of all students"""
if not students_dict:
return "No students found!"
total_grade = sum(student['grade'] for student in students_dict.values())
average = total_grade / len(students_dict)
return f"Class Average: {average:.2f}"
def find_top_student(students_dict):
"""Find student with highest grade"""
if not students_dict:
return "No students found!"
top_student_id = max(students_dict.keys(),
key=lambda x: students_dict[x]['grade'])
top_student = students_dict[top_student_id]
return f"Top Student: {top_student['name']} with grade {top_student['grade']}"
# Test the system
students = {}
# Add students
print(add_student(students, "Rahul", 20, 85))
print(add_student(students, "Priya", 19, 92))
print(add_student(students, "Amit", 21, 78))
# Display information
print(display_student(students, 1))
print(calculate_class_average(students))
print(find_top_student(students))
Common mistakes:
Shortcuts:
*args
for variable number of arguments**kwargs
for keyword argumentsdef add(x: int, y: int) -> int:
Interview tips:
Answers: 1-b, 2-False, 3-b, 4-b, 5-b
Hindi YouTube Videos:
What are Data Structures? Data structures are ways to organize and store data efficiently. They're like different types of containers - some allow changes, some don't, some store unique items, etc.
How they work? Each data structure has specific characteristics:
Syntax & Structure:
# Lists - Square brackets []
fruits = ["apple", "banana", "orange", "apple"]
numbers = [1, 2, 3, 4, 5]
mixed = ["hello", 42, 3.14, True]
# Tuples - Round brackets ()
coordinates = (10, 20)
colors = ("red", "green", "blue")
single_tuple = (42,) # Note the comma
# Sets - Curly brackets {}
unique_numbers = {1, 2, 3, 4, 5}
unique_fruits = {"apple", "banana", "orange"}
# Dictionaries - Curly brackets with key:value pairs
student = {
"name": "Rahul",
"age": 20,
"grade": "A",
"subjects": ["Math", "Science"]
}
# Accessing elements
print(fruits[0]) # apple (list)
print(coordinates[1]) # 20 (tuple)
print(student["name"]) # Rahul (dictionary)
print(3 in unique_numbers) # True (set membership)
Real-world use:
Role in Python projects:
Usage in jobs:
Lists - Most versatile:
# List methods
my_list = [1, 2, 3]
my_list.append(4) # Add to end
my_list.insert(0, 0) # Insert at position
my_list.remove(2) # Remove first occurrence
my_list.pop() # Remove last item
my_list.sort() # Sort in place
len(my_list) # Get length
Tuples - Immutable:
# Tuple operations
point = (3, 4)
x, y = point # Unpacking
count = point.count(3) # Count occurrences
index = point.index(4) # Find index
Sets - Unique elements:
# Set operations
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set1.add(6) # Add element
set1.union(set2) # Combine sets
set1.intersection(set2) # Common elements
set1.difference(set2) # Elements only in set1
Dictionaries - Key-value pairs:
# Dictionary methods
person = {"name": "John", "age": 30}
person["city"] = "Delhi" # Add new key
person.get("age", 0) # Safe access
person.keys() # Get all keys
person.values() # Get all values
person.items() # Get key-value pairs
Exercise 1: Student Grade Management System
# Comprehensive grade management using all data structures
# List to store all students
students_list = []
# Dictionary to store student details
def create_student(name, roll_no, subjects_grades):
"""Create a student dictionary"""
return {
"name": name,
"roll_no": roll_no,
"grades": subjects_grades, # Dictionary of subject:grade
"total": sum(subjects_grades.values()),
"average": sum(subjects_grades.values()) / len(subjects_grades)
}
# Add students
student1 = create_student("Rahul", 101, {"Math": 85, "Science": 90, "English": 78})
student2 = create_student("Priya", 102, {"Math": 92, "Science": 88, "English": 95})
student3 = create_student("Amit", 103, {"Math": 76, "Science": 82, "English": 80})
students_list.extend([student1, student2, student3])
# Tuple for grade boundaries
grade_boundaries = (
(90, "A+"),
(80, "A"),
(70, "B"),
(60, "C"),
(50, "D"),
(0, "F")
)
def get_letter_grade(percentage):
"""Convert percentage to letter grade using tuple"""
for boundary, letter in grade_boundaries:
if percentage >= boundary:
return letter
return "F"
# Set to store unique subjects
all_subjects = set()
for student in students_list:
all_subjects.update(student["grades"].keys())
print("All Subjects:", all_subjects)
# Display student information
for student in students_list:
print(f"\nStudent: {student['name']}")
print(f"Roll No: {student['roll_no']}")
print(f"Grades: {student['grades']}")
print(f"Average: {student['average']:.2f}")
print(f"Letter Grade: {get_letter_grade(student['average'])}")
# Find top performer
top_student = max(students_list, key=lambda x: x['average'])
print(f"\nTop Performer: {top_student['name']} with {top_student['average']:.2f}%")
# Subject-wise analysis
subject_totals = {}
for subject in all_subjects:
total = sum(student["grades"][subject] for student in students_list)
subject_totals[subject] = total / len(students_list)
print("\nSubject-wise Class Averages:")
for subject, avg in subject_totals.items():
print(f"{subject}: {avg:.2f}")
Exercise 2: Inventory Management System
# Inventory system using different data structures
# Dictionary for main inventory
inventory = {}
# Set for categories
categories = {"Electronics", "Clothing", "Books", "Food"}
# List for transaction history
transaction_history = []
def add_item(item_id, name, category, quantity, price):
"""Add item to inventory"""
if category not in categories:
return f"Invalid category. Available: {categories}"
inventory[item_id] = {
"name": name,
"category": category,
"quantity": quantity,
"price": price
}
# Record transaction
transaction_history.append(("ADD", item_id, quantity, "Added to inventory"))
return f"Item {name} added successfully!"
def update_stock(item_id, quantity_change, operation="ADD"):
"""Update item stock"""
if item_id not in inventory:
return "Item not found!"
if operation == "ADD":
inventory[item_id]["quantity"] += quantity_change
transaction_history.append(("RESTOCK", item_id, quantity_change, "Stock added"))
elif operation == "REMOVE":
if inventory[item_id]["quantity"] >= quantity_change:
inventory[item_id]["quantity"] -= quantity_change
transaction_history.append(("SALE", item_id, quantity_change, "Item sold"))
else:
return "Insufficient stock!"
return f"Stock updated. New quantity: {inventory[item_id]['quantity']}"
def get_low_stock_items(threshold=5):
"""Get items with low stock using list comprehension"""
low_stock = [
(item_id, details["name"], details["quantity"])
for item_id, details in inventory.items()
if details["quantity"] <= threshold
]
return low_stock
def get_category_summary():
"""Get summary by category using dictionary comprehension"""
category_summary = {}
for category in categories:
items_in_category = [
item for item in inventory.values()
if item["category"] == category
]
category_summary[category] = {
"total_items": len(items_in_category),
"total_value": sum(item["quantity"] * item["price"] for item in items_in_category)
}
return category_summary
# Test the system
print(add_item("E001", "Laptop", "Electronics", 10, 50000))
print(add_item("C001", "T-Shirt", "Clothing", 25, 500))
print(add_item("B001", "Python Book", "Books", 15, 800))
print(add_item("F001", "Rice", "Food", 100, 50))
print("\nInventory:")
for item_id, details in inventory.items():
print(f"{item_id}: {details}")
print(f"\nUpdate stock: {update_stock('E001', 5, 'REMOVE')}")
print(f"Update stock: {update_stock('C001', 10, 'ADD')}")
print(f"\nLow stock items: {get_low_stock_items(20)}")
print("\nCategory Summary:")
for category, summary in get_category_summary().items():
print(f"{category}: {summary}")
print(f"\nTransaction History (Last 3):")
for transaction in transaction_history[-3:]:
print(transaction)
Exercise 3: Social Media Data Analysis
# Social media data analysis using data structures
# List of posts (each post is a dictionary)
social_media_posts = [
{"user": "rahul123", "content": "Learning Python is fun!", "likes": 15, "tags": ["python", "coding", "learning"]},
{"user": "priya_dev", "content": "Just finished my first project", "likes": 23, "tags": ["project", "coding", "achievement"]},
{"user": "amit_coder", "content": "Python vs Java debate", "likes": 8, "tags": ["python", "java", "programming"]},
{"user": "rahul123", "content": "Data structures are important", "likes": 12, "tags": ["datastructures", "python", "coding"]},
{"user": "tech_guru", "content": "AI is the future", "likes": 45, "tags": ["ai", "future", "technology"]},
]
# Set to store unique users
unique_users = set(post["user"] for post in social_media_posts)
# Dictionary to store user statistics
user_stats = {}
def analyze_user_activity():
"""Analyze user activity and engagement"""
for user in unique_users:
user_posts = [post for post in social_media_posts if post["user"] == user]
total_likes = sum(post["likes"] for post in user_posts)
user_stats[user] = {
"total_posts": len(user_posts),
"total_likes": total_likes,
"average_likes": total_likes / len(user_posts) if user_posts else 0,
"posts": user_posts
}
def get_trending_tags():
"""Find trending hashtags using dictionary"""
tag_count = {}
for post in social_media_posts:
for tag in post["tags"]:
tag_count[tag] = tag_count.get(tag, 0) + 1
# Sort tags by frequency
trending_tags = sorted(tag_count.items(), key=lambda x: x[1], reverse=True)
return trending_tags
def get_top_posts(limit=3):
"""Get top posts by likes"""
sorted_posts = sorted(social_media_posts, key=lambda x: x["likes"], reverse=True)
return sorted_posts[:limit]
def user_engagement_report():
"""Generate comprehensive engagement report"""
analyze_user_activity()
print("=== SOCIAL MEDIA ANALYTICS REPORT ===\n")
print(f"Total Users: {len(unique_users)}")
print(f"Total Posts: {len(social_media_posts)}")
print(f"Total Likes: {sum(post['likes'] for post in social_media_posts)}")
print("\n--- USER STATISTICS ---")
for user, stats in user_stats.items():
print(f"{user}:")
print(f" Posts: {stats['total_posts']}")
print(f" Total Likes: {stats['total_likes']}")
print(f" Avg Likes per Post: {stats['average_likes']:.1f}")
print("\n--- TRENDING TAGS ---")
trending = get_trending_tags()
for tag, count in trending[:5]:
print(f"#{tag}: {count} posts")
print("\n--- TOP POSTS ---")
top_posts = get_top_posts()
for i, post in enumerate(top_posts, 1):
print(f"{i}. @{post['user']}: '{post['content']}' ({post['likes']} likes)")
# Find most active user
most_active = max(user_stats.items(), key=lambda x: x[1]['total_posts'])
print(f"\nMost Active User: @{most_active[0]} with {most_active[1]['total_posts']} posts")
# Find most liked user
most_liked = max(user_stats.items(), key=lambda x: x[1]['total_likes'])
print(f"Most Liked User: @{most_liked[0]} with {most_liked[1]['total_likes']} total likes")
# Run the analysis
user_engagement_report()
# Additional analysis: Posts by tag
def posts_by_tag(tag):
"""Get all posts containing a specific tag"""
matching_posts = [
post for post in social_media_posts
if tag.lower() in [t.lower() for t in post["tags"]]
]
return matching_posts
print(f"\n--- POSTS WITH #python TAG ---")
python_posts = posts_by_tag("python")
for post in python_posts:
print(f"@{post['user']}: {post['content']} ({post['likes']} likes)")
Common mistakes:
Shortcuts:
[x*2 for x in range(5)]
{k: v*2 for k, v in dict.items()}
{x for x in list if x > 0}
Interview tips:
Answers: 1-c, 2-False, 3-b, 4-b, 5-b
Hindi YouTube Videos:
What is File Handling? File handling allows your program to read from and write to files on your computer. It's like giving your program the ability to save and retrieve information permanently.
What is Exception Handling? Exception handling is a way to deal with errors that might occur during program execution without crashing the program. It's like having a backup plan when things go wrong.
Syntax & Structure:
# File Handling
# Writing to a file
with open("example.txt", "w") as file:
file.write("Hello, World!")
# Reading from a file
with open("example.txt", "r") as file:
content = file.read()
print(content)
# Exception Handling
try:
# Code that might cause an error
number = int(input("Enter a number: "))
result = 10 / number
print(f"Result: {result}")
except ValueError:
print("Please enter a valid number!")
except ZeroDivisionError:
print("Cannot divide by zero!")
except Exception as e:
print(f"An error occurred: {e}")
else:
print("No errors occurred!")
finally:
print("This always executes!")
Real-world use:
Role in Python projects:
Usage in jobs:
File Modes:
"r" # Read only (default)
"w" # Write only (overwrites existing)
"a" # Append only
"r+" # Read and write
"x" # Create new file (fails if exists)
"b" # Binary mode (e.g., "rb", "wb")
Exception Types:
ValueError # Wrong value type
TypeError # Wrong data type
FileNotFoundError # File doesn't exist
IndexError # List index out of range
KeyError # Dictionary key doesn't exist
ZeroDivisionError # Division by zero
Best practices:
with
statement for file operationsfinally
blockExercise 1: Personal Expense Tracker
# Expense tracker with file handling and error handling
import json
import datetime
from typing import List, Dict
class ExpenseTracker:
def __init__(self, filename="expenses.json"):
self.filename = filename
self.expenses = self.load_expenses()
def load_expenses(self) -> List[Dict]:
"""Load expenses from file with error handling"""
try:
with open(self.filename, "r") as file:
expenses = json.load(file)
print(f"Loaded {len(expenses)} expenses from file.")
return expenses
except FileNotFoundError:
print("No existing expense file found. Starting fresh!")
return []
except json.JSONDecodeError:
print("Error reading expense file. File may be corrupted.")
backup_name = f"{self.filename}.backup"
try:
with open(self.filename, "r") as original:
with open(backup_name, "w") as backup:
backup.write(original.read())
print(f"Corrupted file backed up as {backup_name}")
except Exception as e:
print(f"Could not create backup: {e}")
return []
except Exception as e:
print(f"Unexpected error loading expenses: {e}")
return []
def save_expenses(self):
"""Save expenses to file with error handling"""
try:
with open(self.filename, "w") as file:
json.dump(self.expenses, file, indent=2)
print("Expenses saved successfully!")
except PermissionError:
print("Permission denied. Cannot save to file.")
except Exception as e:
print(f"Error saving expenses: {e}")
def add_expense(self, amount: float, category: str, description: str):
"""Add new expense with validation"""
try:
# Validate amount
if amount <= 0:
raise ValueError("Amount must be positive")
# Validate category
valid_categories = ["Food", "Transport", "Entertainment", "Bills", "Shopping", "Other"]
if category not in valid_categories:
raise ValueError(f"Category must be one of: {valid_categories}")
# Create expense record
expense = {
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"amount": round(amount, 2),
"category": category,
"description": description
}
self.expenses.append(expense)
print(f"Added expense: ₹{amount} for {category}")
except ValueError as e:
print(f"Invalid input: {e}")
except Exception as e:
print(f"Error adding expense: {e}")
def view_expenses(self, category=None):
"""View expenses with optional category filter"""
try:
if not self.expenses:
print("No expenses recorded yet.")
return
filtered_expenses = self.expenses
if category:
filtered_expenses = [exp for exp in self.expenses if exp["category"] == category]
if not filtered_expenses:
print(f"No expenses found for category: {category}")
return
print(f"\n{'Date':<20} {'Category':<15} {'Amount':<10} {'Description'}")
print("-" * 65)
total = 0
for expense in filtered_expenses:
print(f"{expense['date']:<20} {expense['category']:<15} ₹{expense['amount']:<9.2f} {expense['description']}")
total += expense['amount']
print("-" * 65)
print(f"Total: ₹{total:.2f}")
except Exception as e:
print(f"Error viewing expenses: {e}")
def generate_report(self):
"""Generate expense report by category"""
try:
if not self.expenses:
print("No expenses to report.")
return
# Calculate category totals
category_totals = {}
for expense in self.expenses:
category = expense["category"]
category_totals[category] = category_totals.get(category, 0) + expense["amount"]
# Generate report
total_expenses = sum(category_totals.values())
print("\n=== EXPENSE REPORT ===")
print(f"{'Category':<15} {'Amount':<10} {'Percentage'}")
print("-" * 35)
for category, amount in sorted(category_totals.items(), key=lambda x: x[1], reverse=True):
percentage = (amount / total_expenses) * 100
print(f"{category:<15} ₹{amount:<9.2f} {percentage:.1f}%")
print("-" * 35)
print(f"{'Total':<15} ₹{total_expenses:.2f} 100.0%")
# Save report to file
report_filename = f"expense_report_{datetime.datetime.now().strftime('%Y%m%d')}.txt"
with open(report_filename, "w") as report_file:
report_file.write("EXPENSE REPORT\n")
report_file.write("=" * 50 + "\n")
for category, amount in category_totals.items():
percentage = (amount / total_expenses) * 100
report_file.write(f"{category}: ₹{amount:.2f} ({percentage:.1f}%)\n")
report_file.write(f"\nTotal: ₹{total_expenses:.2f}")
print(f"\nReport saved to {report_filename}")
except Exception as e:
print(f"Error generating report: {e}")
# Test the expense tracker
def main():
tracker = ExpenseTracker()
while True:
try:
print("\n=== EXPENSE TRACKER ===")
print("1. Add Expense")
print("2. View All Expenses")
print("3. View by Category")
print("4. Generate Report")
print("5. Save & Exit")
choice = input("Enter your choice (1-5): ").strip()
if choice == "1":
amount = float(input("Enter amount: ₹"))
category = input("Enter category (Food/Transport/Entertainment/Bills/Shopping/Other): ")
description = input("Enter description: ")
tracker.add_expense(amount, category, description)
elif choice == "2":
tracker.view_expenses()
elif choice == "3":
category = input("Enter category to filter: ")
tracker.view_expenses(category)
elif choice == "4":
tracker.generate_report()
elif choice == "5":
tracker.save_expenses()
print("Goodbye!")
break
else:
print("Invalid choice. Please try again.")
except ValueError:
print("Please enter a valid number.")
except KeyboardInterrupt:
print("\nProgram interrupted. Saving expenses...")
tracker.save_expenses()
break
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Uncomment to run
# main()
Exercise 2: Log File Analyzer
# Log file analyzer with comprehensive error handling
import re
import datetime
from collections import defaultdict, Counter
class LogAnalyzer:
def __init__(self, log_file_path):
self.log_file_path = log_file_path
self.log_entries = []
self.error_patterns = {
'ERROR': r'ERROR',
'WARNING': r'WARNING',
'CRITICAL': r'CRITICAL',
'EXCEPTION': r'Exception|Error'
}
def read_log_file(self):
"""Read and parse log file with error handling"""
try:
with open(self.log_file_path, 'r', encoding='utf-8') as file:
lines = file.readlines()
print(f"Successfully read {len(lines)} lines from log file.")
for line_num, line in enumerate(lines, 1):
try:
# Parse log entry (assuming format: TIMESTAMP LEVEL MESSAGE)
parts = line.strip().split(' ', 2)
if len(parts) >= 3:
timestamp_str = parts[0] + ' ' + parts[1]
level = parts[2].split()[0] if parts[2] else 'INFO'
message = ' '.join(parts[2].split()[1:]) if len(parts[2].split()) > 1 else ''
# Try to parse timestamp
try:
timestamp = datetime.datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')
except ValueError:
# If timestamp parsing fails, use current time
timestamp = datetime.datetime.now()
self.log_entries.append({
'line_number': line_num,
'timestamp': timestamp,
'level': level,
'message': message,
'raw_line': line.strip()
})
except Exception as e:
print(f"Error parsing line {line_num}: {e}")
continue
print(f"Successfully parsed {len(self.log_entries)} log entries.")
except FileNotFoundError:
print(f"Log file '{self.log_file_path}' not found.")
# Create a sample log file for demonstration
self.create_sample_log_file()
except PermissionError:
print(f"Permission denied to read '{self.log_file_path}'.")
except UnicodeDecodeError:
print("Error decoding file. Trying with different encoding...")
try:
with open(self.log_file_path, 'r', encoding='latin-1') as file:
content = file.read()
print("File read with latin-1 encoding.")
except Exception as e:
print(f"Could not read file with any encoding: {e}")
except Exception as e:
print(f"Unexpected error reading log file: {e}")
def create_sample_log_file(self):
"""Create a sample log file for demonstration"""
try:
sample_logs = [
"2024-01-15 10:30:15 INFO Application started successfully",
"2024-01-15 10:30:16 INFO User login: user123",
"2024-01-15 10:31:20 WARNING Database connection slow",
"2024-01-15 10:32:45 ERROR Failed to process payment for order #12345",
"2024-01-15 10:33:10 INFO User logout: user123",
"2024-01-15 10:35:22 CRITICAL Database connection lost",
"2024-01-15 10:35:23 ERROR Exception in payment processing: NullPointerException",
"2024-01-15 10:36:00 INFO Database connection restored",
"2024-01-15 10:37:15 WARNING High memory usage detected",
"2024-01-15 10:38:30 INFO Backup process completed"
]
with open(self.log_file_path, 'w') as file:
for log in sample_logs:
file.write(log + '\n')
print(f"Created sample log file: {self.log_file_path}")
self.read_log_file() # Try reading again
except Exception as e:
print(f"Could not create sample log file: {e}")
def analyze_log_levels(self):
"""Analyze distribution of log levels"""
try:
if not self.log_entries:
print("No log entries to analyze.")
return
level_counts = Counter(entry['level'] for entry in self.log_entries)
print("\n=== LOG LEVEL ANALYSIS ===")
print(f"{'Level':<12} {'Count':<8} {'Percentage'}")
print("-" * 30)
total_entries = len(self.log_entries)
for level, count in level_counts.most_common():
percentage = (count / total_entries) * 100
print(f"{level:<12} {count:<8} {percentage:.1f}%")
return level_counts
except Exception as e:
print(f"Error analyzing log levels: {e}")
def find_errors(self):
"""Find and categorize errors"""
try:
error_entries = []
for entry in self.log_entries:
for error_type, pattern in self.error_patterns.items():
if re.search(pattern, entry['level'] + ' ' + entry['message'], re.IGNORECASE):
error_entries.append({
'type': error_type,
'entry': entry
})
break
if not error_entries:
print("No errors found in log file.")
return
print(f"\n=== ERROR ANALYSIS ===")
print(f"Found {len(error_entries)} error entries:")
# Group by error type
errors_by_type = defaultdict(list)
for error in error_entries:
errors_by_type[error['type']].append(error['entry'])
for error_type, entries in errors_by_type.items():
print(f"\n{error_type} ({len(entries)} occurrences):")
for entry in entries[:5]: # Show first 5 of each type
print(f" Line {entry['line_number']}: {entry['timestamp']} - {entry['message']}")
if len(entries) > 5:
print(f" ... and {len(entries) - 5} more")
return error_entries
except Exception as e:
print(f"Error finding errors: {e}")
def generate_summary_report(self):
"""Generate comprehensive summary report"""
try:
if not self.log_entries:
print("No data to generate report.")
return
# Calculate time range
timestamps = [entry['timestamp'] for entry in self.log_entries]
start_time = min(timestamps)
end_time = max(timestamps)
duration = end_time - start_time
# Generate report
report_filename = f"log_analysis_report_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
with open(report_filename, 'w') as report:
report.write("LOG ANALYSIS REPORT\n")
report.write("=" * 50 + "\n\n")
report.write(f"Log File: {self.log_file_path}\n")
report.write(f"Analysis Date: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
report.write(f"Time Range: {start_time} to {end_time}\n")
report.write(f"Duration: {duration}\n")
report.write(f"Total Entries: {len(self.log_entries)}\n\n")
# Log level summary
level_counts = Counter(entry['level'] for entry in self.log_entries)
report.write("LOG LEVEL DISTRIBUTION:\n")
report.write("-" * 25 + "\n")
for level, count in level_counts.most_common():
percentage = (count / len(self.log_entries)) * 100
report.write(f"{level}: {count} ({percentage:.1f}%)\n")
# Error summary
error_entries = []
for entry in self.log_entries:
if any(re.search(pattern, entry['level'] + ' ' + entry['message'], re.IGNORECASE)
for pattern in self.error_patterns.values()):
error_entries.append(entry)
report.write(f"\nERROR SUMMARY:\n")
report.write("-" * 15 + "\n")
report.write(f"Total Errors: {len(error_entries)}\n")
if error_entries:
report.write("\nRecent Errors:\n")
for entry in error_entries[-5:]: # Last 5 errors
report.write(f"{entry['timestamp']}: {entry['message']}\n")
print(f"\nSummary report saved to: {report_filename}")
except Exception as e:
print(f"Error generating summary report: {e}")
# Test the log analyzer
def main():
try:
log_file = input("Enter log file path (or press Enter for demo): ").strip()
if not log_file:
log_file = "sample_application.log"
analyzer = LogAnalyzer(log_file)
analyzer.read_log_file()
if analyzer.log_entries:
analyzer.analyze_log_levels()
analyzer.find_errors()
analyzer.generate_summary_report()
except KeyboardInterrupt:
print("\nAnalysis interrupted by user.")
except Exception as e:
print(f"Unexpected error in main: {e}")
# Uncomment to run
# main()
Exercise 3: Configuration File Manager
# Configuration file manager with validation and error handling
import json
import configparser
import os
from typing import Dict, Any, Union
class ConfigManager:
def __init__(self, config_dir="config"):
self.config_dir = config_dir
self.ensure_config_directory()
# Default configurations
self.default_configs = {
"app_settings": {
"app_name": "My Application",
"version": "1.0.0",
"debug_mode": False,
"max_users": 100,
"timeout": 30
},
"database": {
"host": "localhost",
"port": 5432,
"database": "myapp",
"username": "admin",
"password": "",
"ssl_enabled": True
},
"logging": {
"level": "INFO",
"file_path": "logs/app.log",
"max_file_size": "10MB",
"backup_count": 5
}
}
def ensure_config_directory(self):
"""Create config directory if it doesn't exist"""
try:
if not os.path.exists(self.config_dir):
os.makedirs(self.config_dir)
print(f"Created config directory: {self.config_dir}")
except PermissionError:
print(f"Permission denied creating directory: {self.config_dir}")
self.config_dir = "." # Use current directory as fallback
except Exception as e:
print(f"Error creating config directory: {e}")
self.config_dir = "."
def save_json_config(self, config_name: str, config_data: Dict[str, Any]):
"""Save configuration as JSON file"""
try:
config_path = os.path.join(self.config_dir, f"{config_name}.json")
# Validate config data
if not isinstance(config_data, dict):
raise TypeError("Configuration data must be a dictionary")
# Create backup if file exists
if os.path.exists(config_path):
backup_path = f"{config_path}.backup"
try:
with open(config_path, 'r') as original:
with open(backup_path, 'w') as backup:
backup.write(original.read())
print(f"Created backup: {backup_path}")
except Exception as e:
print(f"Warning: Could not create backup: {e}")
# Save new configuration
with open(config_path, 'w') as file:
json.dump(config_data, file, indent=4, sort_keys=True)
print(f"Configuration saved: {config_path}")
return True
except TypeError as e:
print(f"Invalid data type: {e}")
return False
except PermissionError:
print(f"Permission denied writing to: {config_path}")
return False
except Exception as e:
print(f"Error saving JSON config: {e}")
return False
def load_json_config(self, config_name: str) -> Union[Dict[str, Any], None]:
"""Load configuration from JSON file"""
try:
config_path = os.path.join(self.config_dir, f"{config_name}.json")
with open(config_path, 'r') as file:
config_data = json.load(file)
print(f"Configuration loaded: {config_path}")
return config_data
except FileNotFoundError:
print(f"Config file not found: {config_path}")
# Return default config if available
if config_name in self.default_configs:
print(f"Using default configuration for {config_name}")
return self.default_configs[config_name].copy()
return None
except json.JSONDecodeError as e:
print(f"Invalid JSON in config file: {e}")
# Try to load backup
backup_path = f"{config_path}.backup"
if os.path.exists(backup_path):
try:
with open(backup_path, 'r') as file:
config_data = json.load(file)
print(f"Loaded from backup: {backup_path}")
return config_data
except Exception:
print("Backup file also corrupted")
return None
except Exception as e:
print(f"Error loading JSON config: {e}")
return None
def save_ini_config(self, config_name: str, config_data: Dict[str, Dict[str, Any]]):
"""Save configuration as INI file"""
try:
config_path = os.path.join(self.config_dir, f"{config_name}.ini")
config = configparser.ConfigParser()
# Convert nested dictionary to INI format
for section_name, section_data in config_data.items():
config.add_section(section_name)
for key, value in section_data.items():
config.set(section_name, key, str(value))
with open(config_path, 'w') as file:
config.write(file)
print(f"INI configuration saved: {config_path}")
return True
except Exception as e:
print(f"Error saving INI config: {e}")
return False
def load_ini_config(self, config_name: str) -> Union[Dict[str, Dict[str, str]], None]:
"""Load configuration from INI file"""
try:
config_path = os.path.join(self.config_dir, f"{config_name}.ini")
config = configparser.ConfigParser()
config.read(config_path)
# Convert to nested dictionary
config_dict = {}
for section_name in config.sections():
config_dict[section_name] = dict(config.items(section_name))
print(f"INI configuration loaded: {config_path}")
return config_dict
except FileNotFoundError:
print(f"INI config file not found: {config_path}")
return None
except Exception as e:
print(f"Error loading INI config: {e}")
return None
def validate_config(self, config_name: str, config_data: Dict[str, Any]) -> bool:
"""Validate configuration data"""
try:
if config_name == "database":
required_fields = ["host", "port", "database", "username"]
for field in required_fields:
if field not in config_data:
raise ValueError(f"Missing required field: {field}")
# Validate port number
if not isinstance(config_data["port"], int) or not (1 <= config_data["port"] <= 65535):
raise ValueError("Port must be an integer between 1 and 65535")
elif config_name == "app_settings":
if "max_users" in config_data:
if not isinstance(config_data["max_users"], int) or config_data["max_users"] <= 0:
raise ValueError("max_users must be a positive integer")
if "timeout" in config_data:
if not isinstance(config_data["timeout"], (int, float)) or config_data["timeout"] <= 0:
raise ValueError("timeout must be a positive number")
print(f"Configuration validation passed for: {config_name}")
return True
except ValueError as e:
print(f"Validation error: {e}")
return False
except Exception as e:
print(f"Unexpected validation error: {e}")
return False
def setup_default_configs(self):
"""Set up default configuration files"""
try:
for config_name, config_data in self.default_configs.items():
if self.validate_config(config_name, config_data):
self.save_json_config(config_name, config_data)
# Also save as INI for demonstration
if isinstance(config_data, dict) and all(isinstance(v, dict) for v in config_data.values()):
self.save_ini_config(config_name, config_data)
else:
# Convert flat dict to nested for INI
nested_config = {"main": config_data}
self.save_ini_config(config_name, nested_config)
print("Default configurations created successfully!")
except Exception as e:
print(f"Error setting up default configs: {e}")
def list_configs(self):
"""List all available configuration files"""
try:
if not os.path.exists(self.config_dir):
print("No config directory found.")
return
config_files = [f for f in os.listdir(self.config_dir)
if f.endswith(('.json', '.ini'))]
if not config_files:
print("No configuration files found.")
return
print(f"\nConfiguration files in {self.config_dir}:")
print("-" * 40)
for file in sorted(config_files):
file_path = os.path.join(self.config_dir, file)
try:
file_size = os.path.getsize(file_path)
mod_time = os.path.getmtime(file_path)
mod_date = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d %H:%M:%S')
print(f"{file:<25} {file_size:>8} bytes {mod_date}")
except Exception as e:
print(f"{file:<25} Error reading file info: {e}")
except Exception as e:
print(f"Error listing configs: {e}")
# Test the configuration manager
def main():
try:
config_manager = ConfigManager()
while True:
print("\n=== CONFIGURATION MANAGER ===")
print("1. Setup Default Configs")
print("2. Load JSON Config")
print("3. Save JSON Config")
print("4. Load INI Config")
print("5. List All Configs")
print("6. Exit")
choice = input("Enter your choice (1-6): ").strip()
if choice == "1":
config_manager.setup_default_configs()
elif choice == "2":
config_name = input("Enter config name to load: ").strip()
config_data = config_manager.load_json_config(config_name)
if config_data:
print(f"Loaded configuration:")
print(json.dumps(config_data, indent=2))
elif choice == "3":
config_name = input("Enter config name to save: ").strip()
print("Enter configuration data as JSON:")
try:
config_input = input()
config_data = json.loads(config_input)
if config_manager.validate_config(config_name, config_data):
config_manager.save_json_config(config_name, config_data)
except json.JSONDecodeError:
print("Invalid JSON format!")
elif choice == "4":
config_name = input("Enter INI config name to load: ").strip()
config_data = config_manager.load_ini_config(config_name)
if config_data:
print(f"Loaded INI configuration:")
for section, items in config_data.items():
print(f"[{section}]")
for key, value in items.items():
print(f"{key} = {value}")
print()
elif choice == "5":
config_manager.list_configs()
elif choice == "6":
print("Goodbye!")
break
else:
print("Invalid choice. Please try again.")
except KeyboardInterrupt:
print("\nProgram interrupted by user.")
except Exception as e:
print(f"Unexpected error: {e}")
# Uncomment to run
# main()
Common mistakes:
with
statement)except Exception
)Shortcuts:
pathlib
for modern file path handlingwith
statement) for automatic cleanupjson.dumps()
with indent
parameter for readable JSONInterview tips:
open()
are automatically closed when the program ends.with
statement for file operations?
a) Faster execution b) Automatic file closing c) Better error messagesAnswers: 1-b, 2-True, 3-b, 4-b, 5-b
Hindi YouTube Videos:
What is Object-Oriented Programming? OOP is a programming paradigm that organizes code into objects and classes. Think of it as creating blueprints (classes) to build real-world things (objects) with properties and behaviors.
How it works?
Syntax & Structure:
# Basic class definition
class Car:
# Class attribute (shared by all instances)
wheels = 4
# Constructor method
def __init__(self, brand, model, color):
# Instance attributes (unique to each object)
self.brand = brand
self.model = model
self.color = color
self.is_running = False
# Instance methods
def start_engine(self):
self.is_running = True
return f"{self.brand} {self.model} engine started!"
def stop_engine(self):
self.is_running = False
return f"{self.brand} {self.model} engine stopped!"
def get_info(self):
return f"{self.color} {self.brand} {self.model}"
# Creating objects (instances)
my_car = Car("Toyota", "Camry", "Blue")
friend_car = Car("Honda", "Civic", "Red")
# Using methods
print(my_car.start_engine())
print(my_car.get_info())
Real-world use:
Role in Python projects:
Usage in jobs:
Four Pillars of OOP:
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private attribute
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
class Vehicle:
def __init__(self, brand):
self.brand = brand
def start(self):
return "Vehicle started"
class Car(Vehicle): # Car inherits from Vehicle
def __init__(self, brand, doors):
super().__init__(brand) # Call parent constructor
self.doors = doors
class Dog:
def make_sound(self):
return "Woof!"
class Cat:
def make_sound(self):
return "Meow!"
# Same method, different implementations
animals = [Dog(), Cat()]
for animal in animals:
print(animal.make_sound())
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
Exercise 1: Library Management System
# Comprehensive library management system using OOP principles
from datetime import datetime, timedelta
from typing import List, Optional
import uuid
class Book:
"""Represents a book in the library"""
def __init__(self, title: str, author: str, isbn: str, genre: str, copies: int = 1):
self.book_id = str(uuid.uuid4())[:8] # Unique book ID
self.title = title
self.author = author
self.isbn = isbn
self.genre = genre
self.total_copies = copies
self.available_copies = copies
self.borrowed_count = 0
def __str__(self):
return f"{self.title} by {self.author} (ISBN: {self.isbn})"
def __repr__(self):
return f"Book('{self.title}', '{self.author}', '{self.isbn}')"
def is_available(self) -> bool:
"""Check if book is available for borrowing"""
return self.available_copies > 0
def borrow(self) -> bool:
"""Borrow a copy of the book"""
if self.is_available():
self.available_copies -= 1
self.borrowed_count += 1
return True
return False
def return_book(self) -> bool:
"""Return a copy of the book"""
if self.available_copies < self.total_copies:
self.available_copies += 1
return True
return False
def get_availability_info(self) -> str:
"""Get availability information"""
return f"Available: {self.available_copies}/{self.total_copies}"
class Member:
"""Represents a library member"""
def __init__(self, name: str, email: str, phone: str):
self.member_id = str(uuid.uuid4())[:8]
self.name = name
self.email = email
self.phone = phone
self.borrowed_books: List['BorrowRecord'] = []
self.membership_date = datetime.now()
self.is_active = True
def __str__(self):
return f"Member: {self.name} (ID: {self.member_id})"
def get_borrowed_books_count(self) -> int:
"""Get count of currently borrowed books"""
return len([record for record in self.borrowed_books if not record.is_returned])
def can_borrow_more(self, max_books: int = 5) -> bool:
"""Check if member can borrow more books"""
return self.is_active and self.get_borrowed_books_count() < max_books
def get_overdue_books(self) -> List['BorrowRecord']:
"""Get list of overdue books"""
return [record for record in self.borrowed_books
if not record.is_returned and record.is_overdue()]
class BorrowRecord:
"""Represents a book borrowing record"""
def __init__(self, book: Book, member: Member, borrow_period_days: int = 14):
self.record_id = str(uuid.uuid4())[:8]
self.book = book
self.member = member
self.borrow_date = datetime.now()
self.due_date = self.borrow_date + timedelta(days=borrow_period_days)
self.return_date: Optional[datetime] = None
self.is_returned = False
self.fine_amount = 0.0
def __str__(self):
status = "Returned" if self.is_returned else "Borrowed"
return f"{self.book.title} - {status} by {self.member.name}"
def is_overdue(self) -> bool:
"""Check if the book is overdue"""
if self.is_returned:
return False
return datetime.now() > self.due_date
def calculate_fine(self, fine_per_day: float = 2.0) -> float:
"""Calculate fine for overdue book"""
if not self.is_overdue():
return 0.0
overdue_days = (datetime.now() - self.due_date).days
return overdue_days * fine_per_day
def return_book(self) -> float:
"""Return the book and calculate fine if any"""
if not self.is_returned:
self.return_date = datetime.now()
self.is_returned = True
self.fine_amount = self.calculate_fine()
self.book.return_book()
return self.fine_amount
class Library:
"""Main library management system"""
def __init__(self, name: str):
self.name = name
self.books: List[Book] = []
self.members: List[Member] = []
self.borrow_records: List[BorrowRecord] = []
self.total_fines_collected = 0.0
def add_book(self, title: str, author: str, isbn: str, genre: str, copies: int = 1) -> Book:
"""Add a new book to the library"""
# Check if book already exists
existing_book = self.find_book_by_isbn(isbn)
if existing_book:
existing_book.total_copies += copies
existing_book.available_copies += copies
print(f"Added {copies} more copies of '{title}'")
return existing_book
new_book = Book(title, author, isbn, genre, copies)
self.books.append(new_book)
print(f"Added new book: {new_book}")
return new_book
def register_member(self, name: str, email: str, phone: str) -> Member:
"""Register a new library member"""
new_member = Member(name, email, phone)
self.members.append(new_member)
print(f"Registered new member: {new_member}")
return new_member
def find_book_by_isbn(self, isbn: str) -> Optional[Book]:
"""Find book by ISBN"""
for book in self.books:
if book.isbn == isbn:
return book
return None
def find_member_by_id(self, member_id: str) -> Optional[Member]:
"""Find member by ID"""
for member in self.members:
if member.member_id == member_id:
return member
return None
def search_books(self, query: str) -> List[Book]:
"""Search books by title, author, or genre"""
query = query.lower()
matching_books = []
for book in self.books:
if (query in book.title.lower() or
query in book.author.lower() or
query in book.genre.lower()):
matching_books.append(book)
return matching_books
def borrow_book(self, member_id: str, isbn: str) -> bool:
"""Process book borrowing"""
member = self.find_member_by_id(member_id)
if not member:
print("Member not found!")
return False
if not member.can_borrow_more():
print(f"Member {member.name} cannot borrow more books!")
return False
book = self.find_book_by_isbn(isbn)
if not book:
print("Book not found!")
return False
if not book.is_available():
print(f"'{book.title}' is not available!")
return False
# Process borrowing
if book.borrow():
borrow_record = BorrowRecord(book, member)
self.borrow_records.append(borrow_record)
member.borrowed_books.append(borrow_record)
print(f"Book '{book.title}' borrowed by {member.name}")
print(f"Due date: {borrow_record.due_date.strftime('%Y-%m-%d')}")
return True
return False
def return_book(self, member_id: str, isbn: str) -> bool:
"""Process book return"""
member = self.find_member_by_id(member_id)
if not member:
print("Member not found!")
return False
# Find the borrow record
for record in member.borrowed_books:
if record.book.isbn == isbn and not record.is_returned:
fine = record.return_book()
if fine > 0:
print(f"Book returned with fine: ₹{fine:.2f}")
self.total_fines_collected += fine
else:
print(f"Book '{record.book.title}' returned successfully!")
return True
print("No active borrowing record found for this book!")
return False
def get_overdue_books(self) -> List[BorrowRecord]:
"""Get all overdue books"""
overdue_records = []
for record in self.borrow_records:
if record.is_overdue():
overdue_records.append(record)
return overdue_records
def generate_library_report(self):
"""Generate comprehensive library report"""
print(f"\n{'='*50}")
print(f"LIBRARY REPORT - {self.name}")
print(f"{'='*50}")
print(f"\nBOOK STATISTICS:")
print(f"Total Books: {len(self.books)}")
print(f"Total Copies: {sum(book.total_copies for book in self.books)}")
print(f"Available Copies: {sum(book.available_copies for book in self.books)}")
print(f"Borrowed Copies: {sum(book.total_copies - book.available_copies for book in self.books)}")
print(f"\nMEMBER STATISTICS:")
print(f"Total Members: {len(self.members)}")
active_members = len([m for m in self.members if m.is_active])
print(f"Active Members: {active_members}")
print(f"\nBORROWING STATISTICS:")
print(f"Total Borrow Records: {len(self.borrow_records)}")
active_borrows = len([r for r in self.borrow_records if not r.is_returned])
print(f"Active Borrows: {active_borrows}")
overdue_books = self.get_overdue_books()
print(f"Overdue Books: {len(overdue_books)}")
print(f"Total Fines Collected: ₹{self.total_fines_collected:.2f}")
if overdue_books:
print(f"\nOVERDUE BOOKS:")
for record in overdue_books[:5]: # Show first 5
days_overdue = (datetime.now() - record.due_date).days
print(f"- {record.book.title} by {record.member.name} ({days_overdue} days overdue)")
# Popular books
popular_books = sorted(self.books, key=lambda x: x.borrowed_count, reverse=True)[:5]
print(f"\nMOST POPULAR BOOKS:")
for book in popular_books:
print(f"- {book.title} (borrowed {book.borrowed_count} times)")
# Test the Library Management System
def main():
# Create library
library = Library("City Central Library")
# Add books
library.add_book("Python Programming", "John Smith", "978-1234567890", "Programming", 3)
library.add_book("Data Science Handbook", "Jane Doe", "978-1234567891", "Data Science", 2)
library.add_book("Web Development", "Bob Johnson", "978-1234567892", "Programming", 2)
library.add_book("Machine Learning", "Alice Brown", "978-1234567893", "AI/ML", 1)
# Register members
member1 = library.register_member("Rahul Kumar", "rahul@email.com", "9876543210")
member2 = library.register_member("Priya Sharma", "priya@email.com", "9876543211")
# Borrow books
print("\n--- BORROWING BOOKS ---")
library.borrow_book(member1.member_id, "978-1234567890")
library.borrow_book(member1.member_id, "978-1234567891")
library.borrow_book(member2.member_id, "978-1234567892")
# Search books
print("\n--- SEARCHING BOOKS ---")
search_results = library.search_books("python")
print(f"Search results for 'python': {len(search_results)} books found")
for book in search_results:
print(f"- {book} ({book.get_availability_info()})")
# Return a book
print("\n--- RETURNING BOOKS ---")
library.return_book(member1.member_id, "978-1234567890")
# Generate report
library.generate_library_report()
# Uncomment to run
# main()
Exercise 2: E-commerce System
# E-commerce system demonstrating advanced OOP concepts
from datetime import datetime
from enum import Enum
from typing import List, Dict, Optional
import uuid
class OrderStatus(Enum):
"""Enum for order status"""
PENDING = "pending"
CONFIRMED = "confirmed"
SHIPPED = "shipped"
DELIVERED = "delivered"
CANCELLED = "cancelled"
class PaymentMethod(Enum):
"""Enum for payment methods"""
CREDIT_CARD = "credit_card"
DEBIT_CARD = "debit_card"
UPI = "upi"
CASH_ON_DELIVERY = "cod"
class Product:
"""Base product class"""
def __init__(self, name: str, price: float, category: str, stock: int, description: str = ""):
self.product_id = str(uuid.uuid4())[:8]
self.name = name
self.price = price
self.category = category
self.stock = stock
self.description = description
self.ratings: List[int] = []
self.reviews: List[str] = []
self.created_date = datetime.now()
def __str__(self):
return f"{self.name} - ₹{self.price} ({self.stock} in stock)"
def __repr__(self):
return f"Product('{self.name}', {self.price}, '{self.category}')"
def is_available(self, quantity: int = 1) -> bool:
"""Check if product is available in required quantity"""
return self.stock >= quantity
def update_stock(self, quantity: int) -> bool:
"""Update stock after purchase"""
if self.stock >= quantity:
self.stock -= quantity
return True
return False
def add_rating(self, rating: int):
"""Add rating (1-5 stars)"""
if 1 <= rating <= 5:
self.ratings.append(rating)
def get_average_rating(self) -> float:
"""Calculate average rating"""
if not self.ratings:
return 0.0
return sum(self.ratings) / len(self.ratings)
def add_review(self, review: str):
"""Add customer review"""
self.reviews.append(review)
def apply_discount(self, discount_percent: float) -> float:
"""Apply discount and return discounted price"""
if 0 <= discount_percent <= 100:
return self.price * (1 - discount_percent / 100)
return self.price
class Electronics(Product):
"""Electronics product with warranty"""
def __init__(self, name: str, price: float, stock: int, brand: str, warranty_months: int, description: str = ""):
super().__init__(name, price, "Electronics", stock, description)
self.brand = brand
self.warranty_months = warranty_months
def __str__(self):
return f"{self.brand} {self.name} - ₹{self.price} ({self.warranty_months}M warranty)"
def get_warranty_info(self) -> str:
"""Get warranty information"""
return f"{self.warranty_months} months warranty from {self.brand}"
class Clothing(Product):
"""Clothing product with size and color"""
def __init__(self, name: str, price: float, stock: int, size: str, color: str, material: str, description: str = ""):
super().__init__(name, price, "Clothing", stock, description)
self.size = size
self.color = color
self.material = material
def __str__(self):
return f"{self.name} ({self.size}, {self.color}) - ₹{self.price}"
def get_size_info(self) -> str:
"""Get size and material information"""
return f"Size: {self.size}, Material: {self.material}, Color: {self.color}"
class Customer:
"""Customer class with shopping cart and order history"""
def __init__(self, name: str, email: str, phone: str, address: str):
self.customer_id = str(uuid.uuid4())[:8]
self.name = name
self.email = email
self.phone = phone
self.address = address
self.cart: 'ShoppingCart' = ShoppingCart(self)
self.orders: List['Order'] = []
self.wishlist: List[Product] = []
self.registration_date = datetime.now()
def __str__(self):
return f"Customer: {self.name} (ID: {self.customer_id})"
def add_to_cart(self, product: Product, quantity: int = 1) -> bool:
"""Add product to shopping cart"""
return self.cart.add_item(product, quantity)
def add_to_wishlist(self, product: Product):
"""Add product to wishlist"""
if product not in self.wishlist:
self.wishlist.append(product)
print(f"Added {product.name} to wishlist")
def remove_from_wishlist(self, product: Product):
"""Remove product from wishlist"""
if product in self.wishlist:
self.wishlist.remove(product)
print(f"Removed {product.name} from wishlist")
def place_order(self, payment_method: PaymentMethod) -> Optional['Order']:
"""Place order from cart"""
if self.cart.is_empty():
print("Cart is empty!")
return None
order = Order(self, payment_method)
for item in self.cart.items:
order.add_item(item.product, item.quantity, item.get_total_price())
if order.process_order():
self.orders.append(order)
self.cart.clear()
print(f"Order placed successfully! Order ID: {order.order_id}")
return order
return None
def get_order_history(self) -> List['Order']:
"""Get customer's order history"""
return sorted(self.orders, key=lambda x: x.order_date, reverse=True)
class CartItem:
"""Individual item in shopping cart"""
def __init__(self, product: Product, quantity: int):
self.product = product
self.quantity = quantity
def get_total_price(self) -> float:
"""Calculate total price for this item"""
return self.product.price * self.quantity
def update_quantity(self, new_quantity: int) -> bool:
"""Update quantity if stock allows"""
if self.product.is_available(new_quantity):
self.quantity = new_quantity
return True
return False
class ShoppingCart:
"""Shopping cart for customers"""
def __init__(self, customer: Customer):
self.customer = customer
self.items: List[CartItem] = []
self.created_date = datetime.now()
def add_item(self, product: Product, quantity: int = 1) -> bool:
"""Add item to cart"""
if not product.is_available(quantity):
print(f"Only {product.stock} units of {product.name} available!")
return False
# Check if item already exists in cart
for item in self.items:
if item.product.product_id == product.product_id:
new_quantity = item.quantity + quantity
if product.is_available(new_quantity):
item.quantity = new_quantity
print(f"Updated {product.name} quantity to {new_quantity}")
return True
else:
print(f"Cannot add more. Only {product.stock} units available!")
return False
# Add new item
cart_item = CartItem(product, quantity)
self.items.append(cart_item)
print(f"Added {quantity} x {product.name} to cart")
return True
def remove_item(self, product_id: str) -> bool:
"""Remove item from cart"""
for item in self.items:
if item.product.product_id == product_id:
self.items.remove(item)
print(f"Removed {item.product.name} from cart")
return True
return False
def update_item_quantity(self, product_id: str, new_quantity: int) -> bool:
"""Update item quantity"""
for item in self.items:
if item.product.product_id == product_id:
if new_quantity <= 0:
return self.remove_item(product_id)
return item.update_quantity(new_quantity)
return False
def get_total_price(self) -> float:
"""Calculate total cart price"""
return sum(item.get_total_price() for item in self.items)
def get_total_items(self) -> int:
"""Get total number of items"""
return sum(item.quantity for item in self.items)
def is_empty(self) -> bool:
"""Check if cart is empty"""
return len(self.items) == 0
def clear(self):
"""Clear all items from cart"""
self.items.clear()
def display_cart(self):
"""Display cart contents"""
if self.is_empty():
print("Cart is empty!")
return
print(f"\n--- SHOPPING CART ({self.customer.name}) ---")
print(f"{'Product':<25} {'Quantity':<10} {'Price':<10} {'Total':<10}")
print("-" * 65)
for item in self.items:
print(f"{item.product.name:<25} {item.quantity:<10} ₹{item.product.price:<9.2f} ₹{item.get_total_price():<9.2f}")
print("-" * 65)
print(f"{'Total Items:':<35} {self.get_total_items()}")
print(f"{'Total Amount:':<35} ₹{self.get_total_price():.2f}")
class Order:
"""Order management class"""
def __init__(self, customer: Customer, payment_method: PaymentMethod):
self.order_id = str(uuid.uuid4())[:8]
self.customer = customer
self.payment_method = payment_method
self.items: List[Dict] = []
self.order_date = datetime.now()
self.status = OrderStatus.PENDING
self.total_amount = 0.0
self.shipping_address = customer.address
self.tracking_number: Optional[str] = None
def add_item(self, product: Product, quantity: int, price: float):
"""Add item to order"""
order_item = {
'product': product,
'quantity': quantity,
'unit_price': product.price,
'total_price': price
}
self.items.append(order_item)
self.total_amount += price
def process_order(self) -> bool:
"""Process the order"""
try:
# Check stock availability and update
for item in self.items:
product = item['product']
quantity = item['quantity']
if not product.is_available(quantity):
print(f"Insufficient stock for {product.name}")
return False
# Update stock for all items
for item in self.items:
product = item['product']
quantity = item['quantity']
product.update_stock(quantity)
self.status = OrderStatus.CONFIRMED
print(f"Order {self.order_id} confirmed!")
return True
except Exception as e:
print(f"Error processing order: {e}")
return False
def ship_order(self) -> bool:
"""Ship the order"""
if self.status == OrderStatus.CONFIRMED:
self.status = OrderStatus.SHIPPED
self.tracking_number = f"TRK{uuid.uuid4().hex[:8].upper()}"
print(f"Order {self.order_id} shipped! Tracking: {self.tracking_number}")
return True
return False
def deliver_order(self) -> bool:
"""Mark order as delivered"""
if self.status == OrderStatus.SHIPPED:
self.status = OrderStatus.DELIVERED
print(f"Order {self.order_id} delivered!")
return True
return False
def cancel_order(self) -> bool:
"""Cancel the order"""
if self.status in [OrderStatus.PENDING, OrderStatus.CONFIRMED]:
# Restore stock
for item in self.items:
product = item['product']
quantity = item['quantity']
product.stock += quantity
self.status = OrderStatus.CANCELLED
print(f"Order {self.order_id} cancelled!")
return True
return False
def get_order_summary(self) -> str:
"""Get order summary"""
summary = f"\nORDER SUMMARY - {self.order_id}\n"
summary += f"Customer: {self.customer.name}\n"
summary += f"Date: {self.order_date.strftime('%Y-%m-%d %H:%M:%S')}\n"
summary += f"Status: {self.status.value.upper()}\n"
summary += f"Payment: {self.payment_method.value.upper()}\n"
if self.tracking_number:
summary += f"Tracking: {self.tracking_number}\n"
summary += f"\nITEMS:\n"
for item in self.items:
summary += f"- {item['product'].name} x{item['quantity']} = ₹{item['total_price']:.2f}\n"
summary += f"\nTotal Amount: ₹{self.total_amount:.2f}"
return summary
class ECommerceStore:
"""Main e-commerce store management"""
def __init__(self, name: str):
self.name = name
self.products: List[Product] = []
self.customers: List[Customer] = []
self.orders: List[Order] = []
self.categories: Dict[str, List[Product]] = {}
def add_product(self, product: Product):
"""Add product to store"""
self.products.append(product)
# Add to category
if product.category not in self.categories:
self.categories[product.category] = []
self.categories[product.category].append(product)
print(f"Added product: {product}")
def register_customer(self, name: str, email: str, phone: str, address: str) -> Customer:
"""Register new customer"""
customer = Customer(name, email, phone, address)
self.customers.append(customer)
print(f"Registered customer: {customer}")
return customer
def search_products(self, query: str) -> List[Product]:
"""Search products by name or category"""
query = query.lower()
results = []
for product in self.products:
if (query in product.name.lower() or
query in product.category.lower() or
query in product.description.lower()):
results.append(product)
return results
def get_products_by_category(self, category: str) -> List[Product]:
"""Get products by category"""
return self.categories.get(category, [])
def get_top_rated_products(self, limit: int = 5) -> List[Product]:
"""Get top rated products"""
rated_products = [p for p in self.products if p.ratings]
return sorted(rated_products, key=lambda x: x.get_average_rating(), reverse=True)[:limit]
def generate_sales_report(self):
"""Generate sales report"""
print(f"\n{'='*50}")
print(f"SALES REPORT - {self.name}")
print(f"{'='*50}")
total_orders = len(self.orders)
total_revenue = sum(order.total_amount for order in self.orders)
print(f"Total Orders: {total_orders}")
print(f"Total Revenue: ₹{total_revenue:.2f}")
if total_orders > 0:
avg_order_value = total_revenue / total_orders
print(f"Average Order Value: ₹{avg_order_value:.2f}")
# Order status breakdown
status_count = {}
for order in self.orders:
status = order.status.value
status_count[status] = status_count.get(status, 0) + 1
print(f"\nOrder Status Breakdown:")
for status, count in status_count.items():
print(f"- {status.title()}: {count}")
# Top selling products
product_sales = {}
for order in self.orders:
for item in order.items:
product_name = item['product'].name
quantity = item['quantity']
product_sales[product_name] = product_sales.get(product_name, 0) + quantity
if product_sales:
print(f"\nTop Selling Products:")
top_products = sorted(product_sales.items(), key=lambda x: x[1], reverse=True)[:5]
for product, quantity in top_products:
print(f"- {product}: {quantity} units sold")
# Test the E-commerce System
def main():
# Create store
store = ECommerceStore("TechMart Online")
# Add products
laptop = Electronics("Gaming Laptop", 75000, 5, "ASUS", 24, "High-performance gaming laptop")
phone = Electronics("Smartphone", 25000, 10, "Samsung", 12, "Latest Android smartphone")
tshirt = Clothing("Cotton T-Shirt", 500, 20, "L", "Blue", "100% Cotton", "Comfortable cotton t-shirt")
jeans = Clothing("Denim Jeans", 1500, 15, "32", "Black", "Denim", "Stylish black jeans")
store.add_product(laptop)
store.add_product(phone)
store.add_product(tshirt)
store.add_product(jeans)
# Register customers
customer1 = store.register_customer("Rahul Kumar", "rahul@email.com", "9876543210", "123 Main St, Delhi")
customer2 = store.register_customer("Priya Sharma", "priya@email.com", "9876543211", "456 Park Ave, Mumbai")
# Shopping simulation
print("\n--- SHOPPING SIMULATION ---")
# Customer 1 shopping
customer1.add_to_cart(laptop, 1)
customer1.add_to_cart(tshirt, 2)
customer1.cart.display_cart()
# Place order
order1 = customer1.place_order(PaymentMethod.CREDIT_CARD)
if order1:
store.orders.append(order1)
print(order1.get_order_summary())
# Ship order
order1.ship_order()
order1.deliver_order()
# Customer 2 shopping
customer2.add_to_cart(phone, 1)
customer2.add_to_cart(jeans, 1)
customer2.add_to_wishlist(laptop)
order2 = customer2.place_order(PaymentMethod.UPI)
if order2:
store.orders.append(order2)
# Search products
print("\n--- PRODUCT SEARCH ---")
search_results = store.search_products("gaming")
print(f"Search results for 'gaming': {len(search_results)} products")
for product in search_results:
print(f"- {product}")
# Generate report
store.generate_sales_report()
# Uncomment to run
# main()
Exercise 3: Banking System with Advanced OOP
# Advanced banking system demonstrating inheritance, polymorphism, and encapsulation
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from typing import List, Optional, Dict
from enum import Enum
import uuid
class TransactionType(Enum):
"""Transaction types"""
DEPOSIT = "deposit"
WITHDRAWAL = "withdrawal"
TRANSFER = "transfer"
INTEREST = "interest"
FEE = "fee"
class AccountType(Enum):
"""Account types"""
SAVINGS = "savings"
CURRENT = "current"
FIXED_DEPOSIT = "fixed_deposit"
LOAN = "loan"
class Transaction:
"""Transaction record"""
def __init__(self, transaction_type: TransactionType, amount: float,
description: str, balance_after: float):
self.transaction_id = str(uuid.uuid4())[:8]
self.transaction_type = transaction_type
self.amount = amount
self.description = description
self.balance_after = balance_after
self.timestamp = datetime.now()
def __str__(self):
return f"{self.timestamp.strftime('%Y-%m-%d %H:%M')} | {self.transaction_type.value.upper()} | ₹{self.amount:.2f} | {self.description}"
class Account(ABC):
"""Abstract base class for all account types"""
def __init__(self, account_holder: str, initial_balance: float = 0.0):
self.account_number = self._generate_account_number()
self.account_holder = account_holder
self._balance = initial_balance
self.created_date = datetime.now()
self.is_active = True
self.transactions: List[Transaction] = []
# Record initial deposit if any
if initial_balance > 0:
self._add_transaction(TransactionType.DEPOSIT, initial_balance, "Initial deposit")
def _generate_account_number(self) -> str:
"""Generate unique account number"""
return f"ACC{uuid.uuid4().hex[:8].upper()}"
def _add_transaction(self, transaction_type: TransactionType, amount: float, description: str):
"""Add transaction to history"""
transaction = Transaction(transaction_type, amount, description, self._balance)
self.transactions.append(transaction)
@property
def balance(self) -> float:
"""Get current balance"""
return self._balance
@abstractmethod
def get_account_type(self) -> AccountType:
"""Get account type - must be implemented by subclasses"""
pass
@abstractmethod
def calculate_interest(self) -> float:
"""Calculate interest - must be implemented by subclasses"""
pass
def deposit(self, amount: float, description: str = "Deposit") -> bool:
"""Deposit money to account"""
if amount <= 0:
print("Deposit amount must be positive!")
return False
if not self.is_active:
print("Account is inactive!")
return False
self._balance += amount
self._add_transaction(TransactionType.DEPOSIT, amount, description)
print(f"Deposited ₹{amount:.2f}. New balance: ₹{self._balance:.2f}")
return True
def withdraw(self, amount: float, description: str = "Withdrawal") -> bool:
"""Withdraw money from account"""
if amount <= 0:
print("Withdrawal amount must be positive!")
return False
if not self.is_active:
print("Account is inactive!")
return False
if not self._can_withdraw(amount):
return False
self._balance -= amount
self._add_transaction(TransactionType.WITHDRAWAL, amount, description)
print(f"Withdrew ₹{amount:.2f}. New balance: ₹{self._balance:.2f}")
return True
def _can_withdraw(self, amount: float) -> bool:
"""Check if withdrawal is allowed - can be overridden by subclasses"""
if self._balance < amount:
print("Insufficient balance!")
return False
return True
def get_statement(self, days: int = 30) -> List[Transaction]:
"""Get account statement for specified days"""
cutoff_date = datetime.now() - timedelta(days=days)
return [t for t in self.transactions if t.timestamp >= cutoff_date]
def get_account_info(self) -> str:
"""Get account information"""
return f"""
Account Number: {self.account_number}
Account Holder: {self.account_holder}
Account Type: {self.get_account_type().value.title()}
Balance: ₹{self._balance:.2f}
Status: {'Active' if self.is_active else 'Inactive'}
Created: {self.created_date.strftime('%Y-%m-%d')}
Total Transactions: {len(self.transactions)}
""".strip()
class SavingsAccount(Account):
"""Savings account with interest calculation"""
def __init__(self, account_holder: str, initial_balance: float = 0.0,
interest_rate: float = 4.0, min_balance: float = 1000.0):
super().__init__(account_holder, initial_balance)
self.interest_rate = interest_rate # Annual interest rate
self.min_balance = min_balance
self.last_interest_date = datetime.now()
def get_account_type(self) -> AccountType:
return AccountType.SAVINGS
def _can_withdraw(self, amount: float) -> bool:
"""Override to check minimum balance"""
if self._balance - amount < self.min_balance:
print(f"Cannot withdraw! Minimum balance of ₹{self.min_balance:.2f} required.")
return False
return super()._can_withdraw(amount)
def calculate_interest(self) -> float:
"""Calculate monthly interest"""
monthly_rate = self.interest_rate / 12 / 100
return self._balance * monthly_rate
def apply_monthly_interest(self) -> bool:
"""Apply monthly interest"""
if not self.is_active:
return False
interest = self.calculate_interest()
if interest > 0:
self._balance += interest
self._add_transaction(TransactionType.INTEREST, interest, "Monthly interest credit")
self.last_interest_date = datetime.now()
print(f"Interest credited: ₹{interest:.2f}")
return True
return False
class CurrentAccount(Account):
"""Current account with overdraft facility"""
def __init__(self, account_holder: str, initial_balance: float = 0.0,
overdraft_limit: float = 50000.0, monthly_fee: float = 500.0):
super().__init__(account_holder, initial_balance)
self.overdraft_limit = overdraft_limit
self.monthly_fee = monthly_fee
self.last_fee_date = datetime.now()
def get_account_type(self) -> AccountType:
return AccountType.CURRENT
def _can_withdraw(self, amount: float) -> bool:
"""Override to allow overdraft"""
if self._balance - amount < -self.overdraft_limit:
print(f"Overdraft limit of ₹{self.overdraft_limit:.2f} exceeded!")
return False
return True
def calculate_interest(self) -> float:
"""Current accounts don't earn interest"""
return 0.0
def apply_monthly_fee(self) -> bool:
"""Apply monthly maintenance fee"""
if not self.is_active:
return False
self._balance -= self.monthly_fee
self._add_transaction(TransactionType.FEE, self.monthly_fee, "Monthly maintenance fee")
self.last_fee_date = datetime.now()
print(f"Monthly fee deducted: ₹{self.monthly_fee:.2f}")
return True
def get_overdraft_info(self) -> str:
"""Get overdraft information"""
used_overdraft = max(0, -self._balance)
available_overdraft = self.overdraft_limit - used_overdraft
return f"Overdraft Limit: ₹{self.overdraft_limit:.2f}, Used: ₹{used_overdraft:.2f}, Available: ₹{available_overdraft:.2f}"
class FixedDepositAccount(Account):
"""Fixed deposit account with higher interest but withdrawal restrictions"""
def __init__(self, account_holder: str, principal_amount: float,
tenure_months: int, interest_rate: float = 7.0):
super().__init__(account_holder, principal_amount)
self.principal_amount = principal_amount
self.tenure_months = tenure_months
self.interest_rate = interest_rate
self.maturity_date = self.created_date + timedelta(days=tenure_months * 30)
self.is_matured = False
def get_account_type(self) -> AccountType:
return AccountType.FIXED_DEPOSIT
def withdraw(self, amount: float, description: str = "Withdrawal") -> bool:
"""Override to restrict withdrawals before maturity"""
if not self.is_matured and datetime.now() < self.maturity_date:
print("Cannot withdraw from FD before maturity!")
print(f"Maturity date: {self.maturity_date.strftime('%Y-%m-%d')}")
return False
return super().withdraw(amount, description)
def calculate_interest(self) -> float:
"""Calculate compound interest for FD"""
if self.is_matured:
return 0.0
# Calculate compound interest
rate = self.interest_rate / 100
time_years = self.tenure_months / 12
compound_amount = self.principal_amount * ((1 + rate) ** time_years)
return compound_amount - self.principal_amount
def check_maturity(self) -> bool:
"""Check and process maturity"""
if not self.is_matured and datetime.now() >= self.maturity_date:
interest = self.calculate_interest()
self._balance += interest
self._add_transaction(TransactionType.INTEREST, interest, "FD maturity interest")
self.is_matured = True
print(f"FD matured! Interest credited: ₹{interest:.2f}")
return True
return False
def get_fd_info(self) -> str:
"""Get FD specific information"""
days_to_maturity = (self.maturity_date - datetime.now()).days
status = "Matured" if self.is_matured else f"{max(0, days_to_maturity)} days to maturity"
expected_interest = self.calculate_interest()
return f"""
Principal Amount: ₹{self.principal_amount:.2f}
Interest Rate: {self.interest_rate}% p.a.
Tenure: {self.tenure_months} months
Maturity Date: {self.maturity_date.strftime('%Y-%m-%d')}
Status: {status}
Expected Interest: ₹{expected_interest:.2f}
""".strip()
class Customer:
"""Bank customer with multiple accounts"""
def __init__(self, name: str, email: str, phone: str, address: str, pan_number: str):
self.customer_id = str(uuid.uuid4())[:8]
self.name = name
self.email = email
self.phone = phone
self.address = address
self.pan_number = pan_number
self.accounts: List[Account] = []
self.registration_date = datetime.now()
def __str__(self):
return f"Customer: {self.name} (ID: {self.customer_id})"
def add_account(self, account: Account):
"""Add account to customer"""
self.accounts.append(account)
print(f"Account {account.account_number} added to customer {self.name}")
def get_total_balance(self) -> float:
"""Get total balance across all accounts"""
return sum(account.balance for account in self.accounts if account.is_active)
def get_account_summary(self) -> str:
"""Get summary of all accounts"""
summary = f"\nCUSTOMER ACCOUNT SUMMARY - {self.name}\n"
summary += f"Customer ID: {self.customer_id}\n"
summary += f"Total Accounts: {len(self.accounts)}\n"
summary += f"Total Balance: ₹{self.get_total_balance():.2f}\n\n"
for account in self.accounts:
summary += f"Account: {account.account_number}\n"
summary += f"Type: {account.get_account_type().value.title()}\n"
summary += f"Balance: ₹{account.balance:.2f}\n"
summary += f"Status: {'Active' if account.is_active else 'Inactive'}\n\n"
return summary
class Bank:
"""Main bank management system"""
def __init__(self, name: str):
self.name = name
self.customers: List[Customer] = []
self.accounts: Dict[str, Account] = {} # account_number -> Account
self.established_date = datetime.now()
def register_customer(self, name: str, email: str, phone: str, address: str, pan_number: str) -> Customer:
"""Register new customer"""
customer = Customer(name, email, phone, address, pan_number)
self.customers.append(customer)
print(f"Customer registered: {customer}")
return customer
def create_savings_account(self, customer: Customer, initial_balance: float = 0.0) -> SavingsAccount:
"""Create savings account"""
account = SavingsAccount(customer.name, initial_balance)
customer.add_account(account)
self.accounts[account.account_number] = account
return account
def create_current_account(self, customer: Customer, initial_balance: float = 0.0) -> CurrentAccount:
"""Create current account"""
account = CurrentAccount(customer.name, initial_balance)
customer.add_account(account)
self.accounts[account.account_number] = account
return account
def create_fixed_deposit(self, customer: Customer, amount: float, tenure_months: int) -> FixedDepositAccount:
"""Create fixed deposit account"""
account = FixedDepositAccount(customer.name, amount, tenure_months)
customer.add_account(account)
self.accounts[account.account_number] = account
return account
def find_account(self, account_number: str) -> Optional[Account]:
"""Find account by account number"""
return self.accounts.get(account_number)
def transfer_money(self, from_account_number: str, to_account_number: str, amount: float) -> bool:
"""Transfer money between accounts"""
from_account = self.find_account(from_account_number)
to_account = self.find_account(to_account_number)
if not from_account or not to_account:
print("One or both accounts not found!")
return False
if from_account.withdraw(amount, f"Transfer to {to_account_number}"):
to_account.deposit(amount, f"Transfer from {from_account_number}")
print(f"Transfer successful: ₹{amount:.2f} from {from_account_number} to {to_account_number}")
return True
return False
def process_monthly_operations(self):
"""Process monthly interest and fees"""
print("\n--- PROCESSING MONTHLY OPERATIONS ---")
for account in self.accounts.values():
if not account.is_active:
continue
if isinstance(account, SavingsAccount):
account.apply_monthly_interest()
elif isinstance(account, CurrentAccount):
account.apply_monthly_fee()
elif isinstance(account, FixedDepositAccount):
account.check_maturity()
def generate_bank_report(self):
"""Generate comprehensive bank report"""
print(f"\n{'='*60}")
print(f"BANK REPORT - {self.name}")
print(f"{'='*60}")
total_customers = len(self.customers)
total_accounts = len(self.accounts)
total_deposits = sum(max(0, account.balance) for account in self.accounts.values())
print(f"Total Customers: {total_customers}")
print(f"Total Accounts: {total_accounts}")
print(f"Total Deposits: ₹{total_deposits:.2f}")
# Account type breakdown
account_types = {}
for account in self.accounts.values():
acc_type = account.get_account_type().value
account_types[acc_type] = account_types.get(acc_type, 0) + 1
print(f"\nAccount Type Breakdown:")
for acc_type, count in account_types.items():
print(f"- {acc_type.title()}: {count}")
# Top customers by balance
customer_balances = [(customer.name, customer.get_total_balance()) for customer in self.customers]
top_customers = sorted(customer_balances, key=lambda x: x[1], reverse=True)[:5]
print(f"\nTop Customers by Balance:")
for name, balance in top_customers:
print(f"- {name}: ₹{balance:.2f}")
# Test the Banking System
def main():
# Create bank
bank = Bank("National Digital Bank")
# Register customers
customer1 = bank.register_customer("Rahul Kumar", "rahul@email.com", "9876543210", "123 Main St", "ABCDE1234F")
customer2 = bank.register_customer("Priya Sharma", "priya@email.com", "9876543211", "456 Park Ave", "FGHIJ5678K")
# Create accounts
savings1 = bank.create_savings_account(customer1, 10000)
current1 = bank.create_current_account(customer1, 25000)
fd1 = bank.create_fixed_deposit(customer1, 100000, 12)
savings2 = bank.create_savings_account(customer2, 15000)
print("\n--- ACCOUNT OPERATIONS ---")
# Perform transactions
savings1.deposit(5000, "Salary credit")
savings1.withdraw(2000, "ATM withdrawal")
current1.withdraw(30000, "Business payment") # This will use overdraft
# Transfer money
bank.transfer_money(savings2.account_number, savings1.account_number, 3000)
# Display account information
print(savings1.get_account_info())
print(f"\n{current1.get_overdraft_info()}")
print(f"\n{fd1.get_fd_info()}")
# Display customer summary
print(customer1.get_account_summary())
# Process monthly operations
bank.process_monthly_operations()
# Generate bank report
bank.generate_bank_report()
# Display recent transactions
print(f"\n--- RECENT TRANSACTIONS (Savings Account) ---")
recent_transactions = savings1.get_statement(30)
for transaction in recent_transactions[-5:]: # Last 5 transactions
print(transaction)
# Uncomment to run
# main()
Common mistakes:
self
parameter in methodssuper().__init__()
in inheritance_
or __
)Shortcuts:
@property
decorator for getter methods@staticmethod
for methods that don't need instance@classmethod
for alternative constructors__str__
and __repr__
for better object representationInterview tips:
__init__
is called automatically when an object is created.super()
do in inheritance?
a) Creates a new object b) Calls parent class methods c) Deletes the objectAnswers: 1-a, 2-True, 3-b, 4-c, 5-b
Hindi YouTube Videos:
What is this day about? Today is about consolidating everything you've learned by building real projects and practicing common interview questions. This combines practical application with job preparation.
How it works? We'll build 3 comprehensive projects that use all the concepts from previous days, plus practice coding problems that are frequently asked in Python interviews.
Structure:
Real-world use:
Role in Python projects:
Usage in jobs:
Project Development Approach:
Interview Preparation:
Exercise 1: Personal Finance Manager
# Complete Personal Finance Manager Application
# Integrates: OOP, File Handling, Exception Handling, Data Structures
import json
import csv
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from typing import List, Dict, Optional
from enum import Enum
import os
class TransactionCategory(Enum):
"""Transaction categories"""
INCOME = "income"
FOOD = "food"
TRANSPORT = "transport"
ENTERTAINMENT = "entertainment"
BILLS = "bills"
SHOPPING = "shopping"
HEALTHCARE = "healthcare"
EDUCATION = "education"
OTHER = "other"
class Transaction:
"""Individual transaction record"""
def __init__(self, amount: float, category: TransactionCategory,
description: str, transaction_type: str = "expense"):
self.id = datetime.now().strftime("%Y%m%d%H%M%S") + str(hash(description))[-4:]
self.amount = abs(amount) # Always store as positive
self.category = category
self.description = description
self.transaction_type = transaction_type # "income" or "expense"
self.date = datetime.now()
def to_dict(self) -> Dict:
"""Convert transaction to dictionary for JSON storage"""
return {
'id': self.id,
'amount': self.amount,
'category': self.category.value,
'description': self.description,
'transaction_type': self.transaction_type,
'date': self.date.isoformat()
}
@classmethod
def from_dict(cls, data: Dict) -> 'Transaction':
"""Create transaction from dictionary"""
transaction = cls(
amount=data['amount'],
category=TransactionCategory(data['category']),
description=data['description'],
transaction_type=data['transaction_type']
)
transaction.id = data['id']
transaction.date = datetime.fromisoformat(data['date'])
return transaction
def __str__(self):
sign = "+" if self.transaction_type == "income" else "-"
return f"{self.date.strftime('%Y-%m-%d')} | {sign}₹{self.amount:.2f} | {self.category.value.title()} | {self.description}"
class Budget:
"""Budget management for categories"""
def __init__(self, category: TransactionCategory, monthly_limit: float):
self.category = category
self.monthly_limit = monthly_limit
self.current_spent = 0.0
self.month = datetime.now().month
self.year = datetime.now().year
def add_expense(self, amount: float):
"""Add expense to budget tracking"""
current_month = datetime.now().month
current_year = datetime.now().year
# Reset if new month
if current_month != self.month or current_year != self.year:
self.current_spent = 0.0
self.month = current_month
self.year = current_year
self.current_spent += amount
def get_remaining_budget(self) -> float:
"""Get remaining budget for the month"""
return max(0, self.monthly_limit - self.current_spent)
def is_over_budget(self) -> bool:
"""Check if over budget"""
return self.current_spent > self.monthly_limit
def get_budget_status(self) -> str:
"""Get budget status string"""
remaining = self.get_remaining_budget()
percentage_used = (self.current_spent / self.monthly_limit) * 100
status = f"{self.category.value.title()}: ₹{self.current_spent:.2f}/₹{self.monthly_limit:.2f} ({percentage_used:.1f}%)"
if self.is_over_budget():
over_amount = self.current_spent - self.monthly_limit
status += f" - OVER BUDGET by ₹{over_amount:.2f}!"
else:
status += f" - ₹{remaining:.2f} remaining"
return status
class FinanceManager:
"""Main finance management system"""
def __init__(self, data_file: str = "finance_data.json"):
self.data_file = data_file
self.transactions: List[Transaction] = []
self.budgets: Dict[TransactionCategory, Budget] = {}
self.load_data()
def load_data(self):
"""Load data from JSON file"""
try:
if os.path.exists(self.data_file):
with open(self.data_file, 'r') as file:
data = json.load(file)
# Load transactions
for trans_data in data.get('transactions', []):
transaction = Transaction.from_dict(trans_data)
self.transactions.append(transaction)
# Load budgets
for budget_data in data.get('budgets', []):
category = TransactionCategory(budget_data['category'])
budget = Budget(category, budget_data['monthly_limit'])
budget.current_spent = budget_data.get('current_spent', 0.0)
budget.month = budget_data.get('month', datetime.now().month)
budget.year = budget_data.get('year', datetime.now().year)
self.budgets[category] = budget
print(f"Loaded {len(self.transactions)} transactions and {len(self.budgets)} budgets")
else:
print("No existing data file found. Starting fresh!")
except Exception as e:
print(f"Error loading data: {e}")
print("Starting with empty data...")
def save_data(self):
"""Save data to JSON file"""
try:
data = {
'transactions': [trans.to_dict() for trans in self.transactions],
'budgets': [
{
'category': budget.category.value,
'monthly_limit': budget.monthly_limit,
'current_spent': budget.current_spent,
'month': budget.month,
'year': budget.year
}
for budget in self.budgets.values()
]
}
with open(self.data_file, 'w') as file:
json.dump(data, file, indent=2)
print("Data saved successfully!")
except Exception as e:
print(f"Error saving data: {e}")
def add_transaction(self, amount: float, category: TransactionCategory,
description: str, transaction_type: str = "expense") -> bool:
"""Add new transaction"""
try:
if amount <= 0:
print("Amount must be positive!")
return False
transaction = Transaction(amount, category, description, transaction_type)
self.transactions.append(transaction)
# Update budget if it's an expense
if transaction_type == "expense" and category in self.budgets:
self.budgets[category].add_expense(amount)
print(f"Transaction added: {transaction}")
return True
except Exception as e:
print(f"Error adding transaction: {e}")
return False
def set_budget(self, category: TransactionCategory, monthly_limit: float) -> bool:
"""Set or update budget for category"""
try:
if monthly_limit <= 0:
print("Budget limit must be positive!")
return False
if category in self.budgets:
self.budgets[category].monthly_limit = monthly_limit
print(f"Updated budget for {category.value}: ₹{monthly_limit:.2f}")
else:
budget = Budget(category, monthly_limit)
self.budgets[category] = budget
print(f"Set new budget for {category.value}: ₹{monthly_limit:.2f}")
return True
except Exception as e:
print(f"Error setting budget: {e}")
return False
def get_transactions_by_period(self, days: int = 30) -> List[Transaction]:
"""Get transactions for specified period"""
cutoff_date = datetime.now() - timedelta(days=days)
return [t for t in self.transactions if t.date >= cutoff_date]
def get_category_summary(self, days: int = 30) -> Dict[str, Dict]:
"""Get spending summary by category"""
transactions = self.get_transactions_by_period(days)
summary = {}
for transaction in transactions:
category = transaction.category.value
if category not in summary:
summary[category] = {'income': 0.0, 'expense': 0.0, 'count': 0}
summary[category][transaction.transaction_type] += transaction.amount
summary[category]['count'] += 1
return summary
def generate_monthly_report(self):
"""Generate comprehensive monthly report"""
print(f"\n{'='*60}")
print(f"MONTHLY FINANCE REPORT - {datetime.now().strftime('%B %Y')}")
print(f"{'='*60}")
# Get current month transactions
current_month_start = datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
monthly_transactions = [t for t in self.transactions if t.date >= current_month_start]
if not monthly_transactions:
print("No transactions found for current month.")
return
# Calculate totals
total_income = sum(t.amount for t in monthly_transactions if t.transaction_type == "income")
total_expenses = sum(t.amount for t in monthly_transactions if t.transaction_type == "expense")
net_savings = total_income - total_expenses
print(f"Total Income: ₹{total_income:.2f}")
print(f"Total Expenses: ₹{total_expenses:.2f}")
print(f"Net Savings: ₹{net_savings:.2f}")
if total_income > 0:
savings_rate = (net_savings / total_income) * 100
print(f"Savings Rate: {savings_rate:.1f}%")
# Category breakdown
category_summary = {}
for transaction in monthly_transactions:
if transaction.transaction_type == "expense":
category = transaction.category.value
category_summary[category] = category_summary.get(category, 0) + transaction.amount
if category_summary:
print(f"\nExpense Breakdown:")
print("-" * 30)
sorted_categories = sorted(category_summary.items(), key=lambda x: x[1], reverse=True)
for category, amount in sorted_categories:
percentage = (amount / total_expenses) * 100 if total_expenses > 0 else 0
print(f"{category.title():<15}: ₹{amount:>8.2f} ({percentage:>5.1f}%)")
# Budget status
if self.budgets:
print(f"\nBudget Status:")
print("-" * 40)
for budget in self.budgets.values():
print(budget.get_budget_status())
# Top expenses
expense_transactions = [t for t in monthly_transactions if t.transaction_type == "expense"]
if expense_transactions:
top_expenses = sorted(expense_transactions, key=lambda x: x.amount, reverse=True)[:5]
print(f"\nTop 5 Expenses:")
print("-" * 50)
for i, transaction in enumerate(top_expenses, 1):
print(f"{i}. ₹{transaction.amount:.2f} - {transaction.description} ({transaction.category.value})")
def export_to_csv(self, filename: str = None):
"""Export transactions to CSV"""
try:
if filename is None:
filename = f"transactions_{datetime.now().strftime('%Y%m%d')}.csv"
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['Date', 'Type', 'Category', 'Description', 'Amount']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for transaction in sorted(self.transactions, key=lambda x: x.date, reverse=True):
writer.writerow({
'Date': transaction.date.strftime('%Y-%m-%d %H:%M:%S'),
'Type': transaction.transaction_type.title(),
'Category': transaction.category.value.title(),
'Description': transaction.description,
'Amount': transaction.amount
})
print(f"Transactions exported to {filename}")
except Exception as e:
print(f"Error exporting to CSV: {e}")
def create_spending_chart(self):
"""Create spending visualization"""
try:
import matplotlib.pyplot as plt
# Get current month data
current_month_start = datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
monthly_expenses = [t for t in self.transactions
if t.date >= current_month_start and t.transaction_type == "expense"]
if not monthly_expenses:
print("No expense data to visualize.")
return
# Calculate category totals
category_totals = {}
for transaction in monthly_expenses:
category = transaction.category.value.title()
category_totals[category] = category_totals.get(category, 0) + transaction.amount
# Create pie chart
plt.figure(figsize=(10, 8))
plt.pie(category_totals.values(), labels=category_totals.keys(), autopct='%1.1f%%')
plt.title(f'Monthly Spending by Category - {datetime.now().strftime("%B %Y")}')
plt.axis('equal')
# Save chart
chart_filename = f"spending_chart_{datetime.now().strftime('%Y%m%d')}.png"
plt.savefig(chart_filename)
print(f"Spending chart saved as {chart_filename}")
plt.show()
except ImportError:
print("Matplotlib not available. Install with: pip install matplotlib")
except Exception as e:
print(f"Error creating chart: {e}")
def main():
"""Main application interface"""
finance_manager = FinanceManager()
while True:
try:
print(f"\n{'='*50}")
print("PERSONAL FINANCE MANAGER")
print(f"{'='*50}")
print("1. Add Income")
print("2. Add Expense")
print("3. Set Budget")
print("4. View Monthly Report")
print("5. View Recent Transactions")
print("6. Export to CSV")
print("7. Create Spending Chart")
print("8. Save & Exit")
choice = input("\nEnter your choice (1-8): ").strip()
if choice == "1":
amount = float(input("Enter income amount: ₹"))
description = input("Enter description: ")
category = TransactionCategory.INCOME
finance_manager.add_transaction(amount, category, description, "income")
elif choice == "2":
print("\nExpense Categories:")
categories = [cat for cat in TransactionCategory if cat != TransactionCategory.INCOME]
for i, cat in enumerate(categories, 1):
print(f"{i}. {cat.value.title()}")
cat_choice = int(input("Select category (1-8): ")) - 1
if 0 <= cat_choice < len(categories):
category = categories[cat_choice]
amount = float(input("Enter expense amount: ₹"))
description = input("Enter description: ")
finance_manager.add_transaction(amount, category, description, "expense")
else:
print("Invalid category selection!")
elif choice == "3":
print("\nBudget Categories:")
categories = [cat for cat in TransactionCategory if cat != TransactionCategory.INCOME]
for i, cat in enumerate(categories, 1):
print(f"{i}. {cat.value.title()}")
cat_choice = int(input("Select category (1-8): ")) - 1
if 0 <= cat_choice < len(categories):
category = categories[cat_choice]
limit = float(input("Enter monthly budget limit: ₹"))
finance_manager.set_budget(category, limit)
else:
print("Invalid category selection!")
elif choice == "4":
finance_manager.generate_monthly_report()
elif choice == "5":
recent_transactions = finance_manager.get_transactions_by_period(30)
if recent_transactions:
print(f"\nRecent Transactions (Last 30 days):")
print("-" * 80)
for transaction in sorted(recent_transactions, key=lambda x: x.date, reverse=True)[:10]:
print(transaction)
else:
print("No recent transactions found.")
elif choice == "6":
finance_manager.export_to_csv()
elif choice == "7":
finance_manager.create_spending_chart()
elif choice == "8":
finance_manager.save_data()
print("Thank you for using Personal Finance Manager!")
break
else:
print("Invalid choice! Please try again.")
except ValueError:
print("Please enter a valid number!")
except KeyboardInterrupt:
print("\nSaving data before exit...")
finance_manager.save_data()
break
except Exception as e:
print(f"An error occurred: {e}")
# Uncomment to run
# main()
Exercise 2: Web Scraper & Data Analyzer
# Web Scraper and Data Analyzer
# Integrates: Functions, Data Structures, File Handling, Exception Handling
import requests
from bs4 import BeautifulSoup
import json
import csv
from datetime import datetime
from typing import List, Dict, Optional
import time
import re
class WebScraper:
"""Web scraping utility class"""
def __init__(self, delay: float = 1.0):
self.delay = delay # Delay between requests to be respectful
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
def fetch_page(self, url: str) -> Optional[str]:
"""Fetch webpage content"""
try:
time.sleep(self.delay) # Be respectful to servers
response = self.session.get(url, timeout=10)
response.raise_for_status()
return response.text
except requests.RequestException as e:
print(f"Error fetching {url}: {e}")
return None
def parse_html(self, html_content: str) -> BeautifulSoup:
"""Parse HTML content"""
return BeautifulSoup(html_content, 'html.parser')
def extract_links(self, soup: BeautifulSoup, base_url: str = "") -> List[str]:
"""Extract all links from page"""
links = []
for link in soup.find_all('a', href=True):
href = link['href']
if href.startswith('http'):
links.append(href)
elif href.startswith('/') and base_url:
links.append(base_url + href)
return list(set(links)) # Remove duplicates
def extract_text_content(self, soup: BeautifulSoup) -> str:
"""Extract clean text content"""
# Remove script and style elements
for script in soup(["script", "style"]):
script.decompose()
text = soup.get_text()
# Clean up text
lines = (line.strip() for line in text.splitlines())
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
text = ' '.join(chunk for chunk in chunks if chunk)
return text
class NewsArticle:
"""Represents a news article"""
def __init__(self, title: str, content: str, url: str, source: str = ""):
self.title = title
self.content = content
self.url = url
self.source = source
self.scraped_date = datetime.now()
self.word_count = len(content.split())
self.keywords = self.extract_keywords()
def extract_keywords(self) -> List[str]:
"""Extract keywords from content"""
# Simple keyword extraction (in real app, use NLP libraries)
text = (self.title + " " + self.content).lower()
# Remove common words
stop_words = {
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have',
'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
'this', 'that', 'these', 'those', 'i', 'you', 'he', 'she', 'it', 'we', 'they'
}
# Extract words (simple approach)
words = re.findall(r'\b[a-zA-Z]{4,}\b', text)
keywords = [word for word in words if word not in stop_words]
# Count frequency and return top keywords
word_freq = {}
for word in keywords:
word_freq[word] = word_freq.get(word, 0) + 1
# Return top 10 keywords
top_keywords = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:10]
return [word for word, freq in top_keywords]
def to_dict(self) -> Dict:
"""Convert article to dictionary"""
return {
'title': self.title,
'content': self.content,
'url': self.url,
'source': self.source,
'scraped_date': self.scraped_date.isoformat(),
'word_count': self.word_count,
'keywords': self.keywords
}
@classmethod
def from_dict(cls, data: Dict) -> 'NewsArticle':
"""Create article from dictionary"""
article = cls(
title=data['title'],
content=data['content'],
url=data['url'],
source=data.get('source', '')
)
article.scraped_date = datetime.fromisoformat(data['scraped_date'])
article.word_count = data['word_count']
article.keywords = data['keywords']
return article
class NewsAnalyzer:
"""Analyze scraped news data"""
def __init__(self):
self.articles: List[NewsArticle] = []
def add_article(self, article: NewsArticle):
"""Add article to analyzer"""
self.articles.append(article)
def load_articles_from_file(self, filename: str):
"""Load articles from JSON file"""
try:
with open(filename, 'r', encoding='utf-8') as file:
data = json.load(file)
for article_data in data:
article = NewsArticle.from_dict(article_data)
self.articles.append(article)
print(f"Loaded {len(data)} articles from {filename}")
except FileNotFoundError:
print(f"File {filename} not found.")
except Exception as e:
print(f"Error loading articles: {e}")
def save_articles_to_file(self, filename: str):
"""Save articles to JSON file"""
try:
data = [article.to_dict() for article in self.articles]
with open(filename, 'w', encoding='utf-8') as file:
json.dump(data, file, indent=2, ensure_ascii=False)
print(f"Saved {len(self.articles)} articles to {filename}")
except Exception as e:
print(f"Error saving articles: {e}")
def get_keyword_frequency(self) -> Dict[str, int]:
"""Get frequency of all keywords across articles"""
keyword_freq = {}
for article in self.articles:
for keyword in article.keywords:
keyword_freq[keyword] = keyword_freq.get(keyword, 0) + 1
return keyword_freq
def get_trending_topics(self, top_n: int = 10) -> List[tuple]:
"""Get trending topics based on keyword frequency"""
keyword_freq = self.get_keyword_frequency()
return sorted(keyword_freq.items(), key=lambda x: x[1], reverse=True)[:top_n]
def search_articles(self, query: str) -> List[NewsArticle]:
"""Search articles by keyword"""
query = query.lower()
matching_articles = []
for article in self.articles:
if (query in article.title.lower() or
query in article.content.lower() or
query in [kw.lower() for kw in article.keywords]):
matching_articles.append(article)
return matching_articles
def get_articles_by_source(self, source: str) -> List[NewsArticle]:
"""Get articles from specific source"""
return [article for article in self.articles if article.source.lower() == source.lower()]
def generate_summary_report(self):
"""Generate comprehensive analysis report"""
if not self.articles:
print("No articles to analyze.")
return
print(f"\n{'='*60}")
print("NEWS ANALYSIS REPORT")
print(f"{'='*60}")
# Basic statistics
total_articles = len(self.articles)
total_words = sum(article.word_count for article in self.articles)
avg_words = total_words / total_articles if total_articles > 0 else 0
print(f"Total Articles: {total_articles}")
print(f"Total Words: {total_words:,}")
print(f"Average Words per Article: {avg_words:.0f}")
# Date range
if self.articles:
dates = [article.scraped_date for article in self.articles]
earliest = min(dates)
latest = max(dates)
print(f"Date Range: {earliest.strftime('%Y-%m-%d')} to {latest.strftime('%Y-%m-%d')}")
# Source breakdown
sources = {}
for article in self.articles:
source = article.source or "Unknown"
sources[source] = sources.get(source, 0) + 1
if sources:
print(f"\nArticles by Source:")
print("-" * 25)
for source, count in sorted(sources.items(), key=lambda x: x[1], reverse=True):
print(f"{source}: {count}")
# Trending topics
trending = self.get_trending_topics(10)
if trending:
print(f"\nTrending Topics:")
print("-" * 20)
for i, (topic, freq) in enumerate(trending, 1):
print(f"{i:2d}. {topic.title()} ({freq} mentions)")
# Article length distribution
length_ranges = {"Short (0-200)": 0, "Medium (201-500)": 0, "Long (501+)": 0}
for article in self.articles:
if article.word_count <= 200:
length_ranges["Short (0-200)"] += 1
elif article.word_count <= 500:
length_ranges["Medium (201-500)"] += 1
else:
length_ranges["Long (501+)"] += 1
print(f"\nArticle Length Distribution:")
print("-" * 30)
for length_range, count in length_ranges.items():
percentage = (count / total_articles) * 100 if total_articles > 0 else 0
print(f"{length_range}: {count} ({percentage:.1f}%)")
def export_to_csv(self, filename: str = None):
"""Export articles to CSV"""
if not self.articles:
print("No articles to export.")
return
if filename is None:
filename = f"news_analysis_{datetime.now().strftime('%Y%m%d')}.csv"
try:
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['Title', 'Source', 'URL', 'Word Count', 'Keywords', 'Scraped Date']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for article in self.articles:
writer.writerow({
'Title': article.title,
'Source': article.source,
'URL': article.url,
'Word Count': article.word_count,
'Keywords': ', '.join(article.keywords[:5]), # Top 5 keywords
'Scraped Date': article.scraped_date.strftime('%Y-%m-%d %H:%M:%S')
})
print(f"Articles exported to {filename}")
except Exception as e:
print(f"Error exporting to CSV: {e}")
class DemoNewsScraper:
"""Demo news scraper (simulates real scraping)"""
def __init__(self):
# Sample news data for demonstration
self.sample_articles = [
{
'title': 'Python Programming Language Gains Popularity in 2024',
'content': 'Python continues to be one of the most popular programming languages in 2024. Its simplicity and versatility make it ideal for web development, data science, artificial intelligence, and automation. Many companies are adopting Python for their backend systems and data analysis needs. The language\'s extensive library ecosystem and active community support contribute to its growing adoption.',
'source': 'Tech News Daily',
'url': 'https://example.com/python-popularity-2024'
},
{
'title': 'Artificial Intelligence Revolutionizes Healthcare Industry',
'content': 'Artificial intelligence is transforming healthcare with advanced diagnostic tools, personalized treatment plans, and drug discovery acceleration. Machine learning algorithms can now detect diseases earlier and more accurately than traditional methods. AI-powered systems are helping doctors make better decisions and improving patient outcomes across various medical specialties.',
'source': 'Health Tech Review',
'url': 'https://example.com/ai-healthcare-revolution'
},
{
'title': 'Remote Work Trends Continue to Shape Modern Workplace',
'content': 'Remote work has become a permanent fixture in many organizations following the global shift in work patterns. Companies are investing in digital collaboration tools and flexible work policies. Employees report higher job satisfaction and better work-life balance, while employers benefit from access to global talent and reduced overhead costs.',
'source': 'Business Weekly',
'url': 'https://example.com/remote-work-trends'
},
{
'title': 'Sustainable Technology Solutions Gain Momentum',
'content': 'Green technology initiatives are accelerating as companies focus on environmental sustainability. Solar energy, electric vehicles, and energy-efficient data centers are becoming mainstream. Investors are increasingly funding clean technology startups, and governments are implementing policies to support sustainable innovation.',
'source': 'Green Tech Today',
'url': 'https://example.com/sustainable-tech-solutions'
},
{
'title': 'Cybersecurity Threats Evolve with Advanced Attack Methods',
'content': 'Cybersecurity professionals face increasingly sophisticated threats as attackers use artificial intelligence and machine learning to develop new attack vectors. Organizations are investing heavily in security infrastructure, employee training, and incident response capabilities. Zero-trust security models are becoming the new standard for enterprise protection.',
'source': 'Security Alert',
'url': 'https://example.com/cybersecurity-threats-2024'
}
]
def scrape_sample_news(self) -> List[NewsArticle]:
"""Generate sample news articles"""
articles = []
for article_data in self.sample_articles:
article = NewsArticle(
title=article_data['title'],
content=article_data['content'],
url=article_data['url'],
source=article_data['source']
)
articles.append(article)
return articles
def main():
"""Main application interface"""
analyzer = NewsAnalyzer()
scraper = DemoNewsScraper()
# Load existing data if available
analyzer.load_articles_from_file('news_data.json')
while True:
try:
print(f"\n{'='*50}")
print("NEWS SCRAPER & ANALYZER")
print(f"{'='*50}")
print("1. Scrape Sample News")
print("2. View All Articles")
print("3. Search Articles")
print("4. Generate Analysis Report")
print("5. View Trending Topics")
print("6. Export to CSV")
print("7. Save Data")
print("8. Exit")
choice = input("\nEnter your choice (1-8): ").strip()
if choice == "1":
print("Scraping sample news articles...")
sample_articles = scraper.scrape_sample_news()
for article in sample_articles:
analyzer.add_article(article)
print(f"Added {len(sample_articles)} sample articles!")
elif choice == "2":
if not analyzer.articles:
print("No articles available. Please scrape some news first.")
else:
print(f"\nAll Articles ({len(analyzer.articles)} total):")
print("-" * 80)
for i, article in enumerate(analyzer.articles, 1):
print(f"{i}. {article.title}")
print(f" Source: {article.source} | Words: {article.word_count}")
print(f" Keywords: {', '.join(article.keywords[:5])}")
print()
elif choice == "3":
query = input("Enter search query: ").strip()
if query:
results = analyzer.search_articles(query)
if results:
print(f"\nFound {len(results)} articles matching '{query}':")
print("-" * 60)
for article in results:
print(f"• {article.title}")
print(f" Source: {article.source}")
print()
else:
print(f"No articles found matching '{query}'")
elif choice == "4":
analyzer.generate_summary_report()
elif choice == "5":
trending = analyzer.get_trending_topics(15)
if trending:
print(f"\nTop 15 Trending Topics:")
print("-" * 30)
for i, (topic, freq) in enumerate(trending, 1):
print(f"{i:2d}. {topic.title()} ({freq} mentions)")
else:
print("No trending topics available.")
elif choice == "6":
analyzer.export_to_csv()
elif choice == "7":
analyzer.save_articles_to_file('news_data.json')
elif choice == "8":
analyzer.save_articles_to_file('news_data.json')
print("Thank you for using News Scraper & Analyzer!")
break
else:
print("Invalid choice! Please try again.")
except KeyboardInterrupt:
print("\nSaving data before exit...")
analyzer.save_articles_to_file('news_data.json')
break
except Exception as e:
print(f"An error occurred: {e}")
# Uncomment to run
# main()
Exercise 3: Interview Coding Practice
# Common Python Interview Questions with Solutions
# Covers: Algorithms, Data Structures, Problem Solving
def interview_practice():
"""Collection of common interview coding problems"""
print("PYTHON INTERVIEW CODING PRACTICE")
print("=" * 50)
# Problem 1: Two Sum
def two_sum(nums, target):
"""
Find two numbers in array that add up to target
Time: O(n), Space: O(n)
"""
seen = {}
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
print("1. Two Sum Problem:")
nums = [2, 7, 11, 15]
target = 9
result = two_sum(nums, target)
print(f" Input: {nums}, Target: {target}")
print(f" Output: {result}")
print(f" Explanation: nums[{result[0]}] + nums[{result[1]}] = {nums[result[0]]} + {nums[result[1]]} = {target}")
# Problem 2: Palindrome Check
def is_palindrome(s):
"""
Check if string is palindrome (ignoring case and non-alphanumeric)
Time: O(n), Space: O(1)
"""
left, right = 0, len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
print("\n2. Palindrome Check:")
test_strings = ["A man, a plan, a canal: Panama", "race a car", "hello"]
for s in test_strings:
result = is_palindrome(s)
print(f" '{s}' -> {result}")
# Problem 3: Fibonacci Sequence
def fibonacci(n):
"""
Generate fibonacci sequence up to n terms
Time: O(n), Space: O(1)
"""
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
print("\n3. Fibonacci Sequence:")
for n in [5, 8, 10]:
result = fibonacci(n)
print(f" First {n} fibonacci numbers: {result}")
# Problem 4: Find Duplicates
def find_duplicates(nums):
"""
Find all duplicates in array
Time: O(n), Space: O(n)
"""
seen = set()
duplicates = set()
for num in nums:
if num in seen:
duplicates.add(num)
else:
seen.add(num)
return list(duplicates)
print("\n4. Find Duplicates:")
test_arrays = [[1, 2, 3, 2, 4, 5, 1], [4, 3, 2, 7, 8, 2, 3, 1]]
for arr in test_arrays:
result = find_duplicates(arr)
print(f" {arr} -> Duplicates: {result}")
# Problem 5: Reverse Words in String
def reverse_words(s):
"""
Reverse words in a string
Time: O(n), Space: O(n)
"""
words = s.split()
return ' '.join(reversed(words))
print("\n5. Reverse Words:")
test_sentences = ["the sky is blue", " hello world ", "a good example"]
for sentence in test_sentences:
result = reverse_words(sentence)
print(f" '{sentence}' -> '{result}'")
# Problem 6: Valid Parentheses
def is_valid_parentheses(s):
"""
Check if parentheses are valid
Time: O(n), Space: O(n)
"""
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping:
if not stack or stack.pop() != mapping[char]:
return False
else:
stack.append(char)
return not stack
print("\n6. Valid Parentheses:")
test_cases = ["()", "()[]{}", "(]", "([)]", "{[]}"]
for case in test_cases:
result = is_valid_parentheses(case)
print(f" '{case}' -> {result}")
# Problem 7: Maximum Subarray Sum (Kadane's Algorithm)
def max_subarray_sum(nums):
"""
Find maximum sum of contiguous subarray
Time: O(n), Space: O(1)
"""
if not nums:
return 0
max_sum = current_sum = nums[0]
for num in nums[1:]:
current_sum = max(num, current_sum + num)
max_sum = max(max_sum, current_sum)
return max_sum
print("\n7. Maximum Subarray Sum:")
test_arrays = [[-2,1,-3,4,-1,2,1,-5,4], [1], [5,4,-1,7,8]]
for arr in test_arrays:
result = max_subarray_sum(arr)
print(f" {arr} -> Max sum: {result}")
# Problem 8: Binary Search
def binary_search(nums, target):
"""
Binary search in sorted array
Time: O(log n), Space: O(1)
"""
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
print("\n8. Binary Search:")
sorted_array = [1, 3, 5, 7, 9, 11, 13, 15]
targets = [7, 4, 15, 1]
for target in targets:
result = binary_search(sorted_array, target)
print(f" Search {target} in {sorted_array} -> Index: {result}")
# Problem 9: Merge Two Sorted Lists
def merge_sorted_lists(list1, list2):
"""
Merge two sorted lists
Time: O(m + n), Space: O(m + n)
"""
result = []
i = j = 0
while i < len(list1) and j < len(list2):
if list1[i] <= list2[j]:
result.append(list1[i])
i += 1
else:
result.append(list2[j])
j += 1
# Add remaining elements
result.extend(list1[i:])
result.extend(list2[j:])
return result
print("\n9. Merge Sorted Lists:")
test_cases = [
([1, 2, 4], [1, 3, 4]),
([1, 5, 9], [2, 6, 8]),
([], [1, 2, 3])
]
for list1, list2 in test_cases:
result = merge_sorted_lists(list1, list2)
print(f" {list1} + {list2} -> {result}")
# Problem 10: Count Character Frequency
def char_frequency(s):
"""
Count frequency of each character
Time: O(n), Space: O(k) where k is unique characters
"""
freq = {}
for char in s:
freq[char] = freq.get(char, 0) + 1
return freq
print("\n10. Character Frequency:")
test_strings = ["hello", "programming", "aabbcc"]
for s in test_strings:
result = char_frequency(s)
print(f" '{s}' -> {result}")
# Additional Interview Tips and Patterns
def interview_tips():
"""Important interview tips and patterns"""
print("\n" + "="*60)
print("PYTHON INTERVIEW TIPS & PATTERNS")
print("="*60)
print("\n1. COMMON PATTERNS:")
print(" • Two Pointers: Use for arrays/strings")
print(" • Sliding Window: For subarray problems")
print(" • Hash Maps: For O(1) lookups")
print(" • Stack: For parentheses, parsing")
print(" • BFS/DFS: For tree/graph problems")
print("\n2. TIME COMPLEXITY ANALYSIS:")
print(" • O(1): Constant - hash lookup, array access")
print(" • O(log n): Logarithmic - binary search")
print(" • O(n): Linear - single loop")
print(" • O(n log n): Log-linear - efficient sorting")
print(" • O(n²): Quadratic - nested loops")
print("\n3. PYTHON-SPECIFIC TIPS:")
print(" • Use list comprehensions: [x*2 for x in nums]")
print(" • Use enumerate(): for i, val in enumerate(list)")
print(" • Use zip(): for a, b in zip(list1, list2)")
print(" • Use collections.Counter for frequency counting")
print(" • Use collections.defaultdict for default values")
print("\n4. PROBLEM-SOLVING APPROACH:")
print(" 1. Understand the problem completely")
print(" 2. Ask clarifying questions")
print(" 3. Think of brute force solution first")
print(" 4. Optimize using appropriate data structures")
print(" 5. Analyze time and space complexity")
print(" 6. Test with edge cases")
print("\n5. COMMON EDGE CASES:")
print(" • Empty input ([], '', None)")
print(" • Single element")
print(" • All elements same")
print(" • Negative numbers")
print(" • Very large inputs")
print("\n6. CODING INTERVIEW CHECKLIST:")
print(" ✓ Clarify requirements")
print(" ✓ Discuss approach before coding")
print(" ✓ Write clean, readable code")
print(" ✓ Handle edge cases")
print(" ✓ Test your solution")
print(" ✓ Analyze complexity")
print(" ✓ Discuss optimizations")
def main():
"""Run interview practice session"""
try:
interview_practice()
interview_tips()
print(f"\n{'='*60}")
print("PRACTICE COMPLETE!")
print("="*60)
print("Key takeaways:")
print("• Practice these patterns regularly")
print("• Focus on problem-solving approach")
print("• Always analyze time/space complexity")
print("• Write clean, readable code")
print("• Test with multiple examples")
print("\nGood luck with your interviews! 🚀")
except Exception as e:
print(f"Error in practice session: {e}")
# Uncomment to run
# main()
Project Development Tips:
Interview Preparation:
Common Interview Mistakes:
Answers: 1-b, 2-True, 3-b, 4-c, 5-b
Hindi YouTube Videos:
Day 1: Python basics, variables, data types Day 2: Conditional statements, loops, control flow Day 3: Functions, modules, code organization Day 4: Data structures (lists, tuples, sets, dictionaries) Day 5: File handling, exception handling, error management Day 6: Object-oriented programming, classes, inheritance Day 7: Complete projects, interview preparation
Congratulations! You've completed an intensive 7-day Python journey from beginner to job-ready level! 🎉