This page shows the source code for Session-3-1-Examples.py in browser-friendly HTML format. It was generated automatically from the original Python file.
"""
Advanced Python - Session 1: Object-Oriented Programming
Code Examples and Library Management System
"""
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
import csv
# ============================================
# PART 1: Classes and Objects Basics
# ============================================
print("=" * 60)
print("PART 1: Classes and Objects")
print("=" * 60)
class Dog:
"""A simple Dog class"""
# Class variable (shared by all instances)
species = "Canis familiaris"
def __init__(self, name, age, breed):
"""Constructor - initializes instance variables"""
self.name = name # Instance variable
self.age = age
self.breed = breed
def bark(self):
"""Instance method"""
return f"{self.name} says Woof!"
def get_info(self):
"""Return dog information"""
return f"{self.name} is a {self.age}-year-old {self.breed}"
def birthday(self):
"""Increment age"""
self.age += 1
return f"Happy Birthday {self.name}! Now {self.age} years old."
# Creating objects (instances)
print("\n--- Creating Dog Objects ---")
dog1 = Dog("Buddy", 3, "Golden Retriever")
dog2 = Dog("Max", 5, "German Shepherd")
print(dog1.bark())
print(dog2.get_info())
print(dog1.birthday())
print(f"Species: {dog1.species}")
# ============================================
# PART 2: Inheritance
# ============================================
print("\n" + "=" * 60)
print("PART 2: Inheritance")
print("=" * 60)
class Animal:
"""Base class for all animals"""
def __init__(self, name, species):
self.name = name
self.species = species
self.is_alive = True
def speak(self):
return "Some generic animal sound"
def get_info(self):
return f"{self.name} is a {self.species}"
class Cat(Animal):
"""Cat class inheriting from Animal"""
def __init__(self, name, color):
super().__init__(name, "Cat") # Call parent constructor
self.color = color
def speak(self):
"""Override parent method"""
return f"{self.name} says Meow!"
def purr(self):
"""Cat-specific method"""
return f"{self.name} is purring..."
class Bird(Animal):
"""Bird class inheriting from Animal"""
def __init__(self, name, can_fly):
super().__init__(name, "Bird")
self.can_fly = can_fly
def speak(self):
return f"{self.name} says Tweet!"
def fly(self):
if self.can_fly:
return f"{self.name} is flying!"
return f"{self.name} cannot fly."
print("\n--- Animal Inheritance Example ---")
cat = Cat("Whiskers", "Orange")
bird = Bird("Tweety", True)
print(cat.get_info()) # Inherited method
print(cat.speak()) # Overridden method
print(cat.purr()) # Cat-specific method
print(bird.get_info())
print(bird.speak())
print(bird.fly())
# ============================================
# PART 3: Encapsulation
# ============================================
print("\n" + "=" * 60)
print("PART 3: Encapsulation")
print("=" * 60)
class BankAccount:
"""Bank account with encapsulation"""
def __init__(self, owner, initial_balance=0):
self.owner = owner # Public
self._account_number = "ACC123456" # Protected (convention)
self.__balance = initial_balance # Private (name mangling)
def deposit(self, amount):
"""Public method to deposit money"""
if amount > 0:
self.__balance += amount
return f"Deposited ${amount}. New balance: ${self.__balance}"
return "Invalid deposit amount"
def withdraw(self, amount):
"""Public method to withdraw money"""
if amount > self.__balance:
return "Insufficient funds"
if amount > 0:
self.__balance -= amount
return f"Withdrew ${amount}. New balance: ${self.__balance}"
return "Invalid withdrawal amount"
def get_balance(self):
"""Public method to check balance"""
return self.__balance
def __str__(self):
return f"Account({self.owner}): ${self.__balance}"
print("\n--- Bank Account Example ---")
account = BankAccount("Alice", 1000)
print(account.deposit(500))
print(account.withdraw(300))
print(f"Current balance: ${account.get_balance()}")
# print(account.__balance) # This would cause an error!
# ============================================
# PART 4: Property Decorators
# ============================================
print("\n" + "=" * 60)
print("PART 4: Property Decorators")
print("=" * 60)
class Temperature:
"""Temperature class with property decorators"""
def __init__(self, celsius=0):
self._celsius = celsius
@property
def celsius(self):
"""Getter for celsius"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""Setter with validation"""
if value < -273.15:
raise ValueError("Temperature below absolute zero!")
self._celsius = value
@property
def fahrenheit(self):
"""Calculated property"""
return (self._celsius * 9/5) + 32
@fahrenheit.setter
def fahrenheit(self, value):
"""Set celsius from fahrenheit"""
self._celsius = (value - 32) * 5/9
print("\n--- Temperature Property Example ---")
temp = Temperature(25)
print(f"Temperature: {temp.celsius}°C = {temp.fahrenheit}°F")
temp.fahrenheit = 86
print(f"New Temperature: {temp.celsius}°C = {temp.fahrenheit}°F")
# ============================================
# PART 5: Magic Methods (Dunder Methods)
# ============================================
print("\n" + "=" * 60)
print("PART 5: Magic Methods")
print("=" * 60)
class Book:
"""Book class with magic methods"""
def __init__(self, title, author, pages, price):
self.title = title
self.author = author
self.pages = pages
self.price = price
def __str__(self):
"""User-friendly string representation"""
return f"'{self.title}' by {self.author}"
def __repr__(self):
"""Developer-friendly representation"""
return f"Book('{self.title}', '{self.author}', {self.pages}, ${self.price})"
def __len__(self):
"""Return number of pages"""
return self.pages
def __eq__(self, other):
"""Check equality"""
return (self.title == other.title and
self.author == other.author)
def __lt__(self, other):
"""Less than comparison (by pages)"""
return self.pages < other.pages
def __add__(self, other):
"""Add books (combine pages)"""
return self.pages + other.pages
print("\n--- Magic Methods Example ---")
book1 = Book("1984", "George Orwell", 328, 15.99)
book2 = Book("Animal Farm", "George Orwell", 112, 12.99)
book3 = Book("1984", "George Orwell", 328, 15.99)
print(str(book1)) # Calls __str__
print(repr(book1)) # Calls __repr__
print(f"Pages: {len(book1)}") # Calls __len__
print(f"book1 == book3: {book1 == book3}") # Calls __eq__
print(f"book1 < book2: {book1 < book2}") # Calls __lt__
print(f"Total pages: {book1 + book2}") # Calls __add__
# ============================================
# PART 6: Class Methods and Static Methods
# ============================================
print("\n" + "=" * 60)
print("PART 6: Class Methods and Static Methods")
print("=" * 60)
class Employee:
"""Employee class with class and static methods"""
num_employees = 0
raise_amount = 1.04
def __init__(self, first, last, salary):
self.first = first
self.last = last
self.salary = salary
Employee.num_employees += 1
@property
def email(self):
"""Generate email"""
return f"{self.first.lower()}.{self.last.lower()}@company.com"
@property
def fullname(self):
return f"{self.first} {self.last}"
def apply_raise(self):
"""Instance method"""
self.salary = int(self.salary * self.raise_amount)
@classmethod
def set_raise_amount(cls, amount):
"""Class method to modify class variable"""
cls.raise_amount = amount
@classmethod
def from_string(cls, emp_string):
"""Alternative constructor"""
first, last, salary = emp_string.split('-')
return cls(first, last, int(salary))
@staticmethod
def is_workday(day):
"""Static method - doesn't need instance or class"""
if day.weekday() == 5 or day.weekday() == 6:
return False
return True
def __str__(self):
return f"{self.fullname}: ${self.salary}"
print("\n--- Employee Class Example ---")
emp1 = Employee("John", "Doe", 50000)
emp2 = Employee.from_string("Jane-Smith-60000") # Using class method
print(emp1)
print(f"Email: {emp1.email}")
print(f"Total employees: {Employee.num_employees}")
emp1.apply_raise()
print(f"After raise: {emp1}")
# Using static method
import datetime
my_date = datetime.date(2025, 1, 20)
print(f"Is {my_date} a workday? {Employee.is_workday(my_date)}")
# ============================================
# PART 7: Abstract Classes
# ============================================
print("\n" + "=" * 60)
print("PART 7: Abstract Classes")
print("=" * 60)
class Shape(ABC):
"""Abstract base class for shapes"""
def __init__(self, name):
self.name = name
@abstractmethod
def area(self):
"""Must be implemented by subclasses"""
pass
@abstractmethod
def perimeter(self):
"""Must be implemented by subclasses"""
pass
def describe(self):
"""Concrete method"""
return f"This is a {self.name}"
class Rectangle(Shape):
def __init__(self, width, height):
super().__init__("Rectangle")
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
def perimeter(self):
return 2 * 3.14159 * self.radius
print("\n--- Shape Abstract Class Example ---")
rect = Rectangle(5, 10)
circle = Circle(7)
print(f"{rect.describe()}: Area = {rect.area()}, Perimeter = {rect.perimeter()}")
print(f"{circle.describe()}: Area = {circle.area():.2f}, Circumference = {circle.perimeter():.2f}")
# ============================================
# PART 8: Complete Project - Library Management System
# ============================================
print("\n" + "=" * 60)
print("PART 8: Library Management System")
print("=" * 60)
class Book:
"""Represents a book in the library"""
def __init__(self, isbn, title, author, year, genre):
self.isbn = isbn
self.title = title
self.author = author
self.year = year
self.genre = genre
self.is_available = True
self.borrowed_by = None
self.due_date = None
def __str__(self):
status = "Available" if self.is_available else f"Borrowed (due: {self.due_date})"
return f"[{self.isbn}] '{self.title}' by {self.author} ({self.year}) - {status}"
def __repr__(self):
return f"Book('{self.isbn}', '{self.title}', '{self.author}')"
class Member:
"""Represents a library member"""
def __init__(self, member_id, name, email):
self.member_id = member_id
self.name = name
self.email = email
self.borrowed_books = []
self.join_date = datetime.now()
def can_borrow(self):
"""Check if member can borrow more books"""
return len(self.borrowed_books) < 3
def __str__(self):
return f"Member {self.member_id}: {self.name} ({len(self.borrowed_books)} books borrowed)"
def __repr__(self):
return f"Member('{self.member_id}', '{self.name}')"
class Library:
"""Main library management system"""
def __init__(self, name):
self.name = name
self.books = {} # ISBN -> Book
self.members = {} # member_id -> Member
def add_book(self, book):
"""Add a book to the library"""
if book.isbn in self.books:
return f"Book with ISBN {book.isbn} already exists"
self.books[book.isbn] = book
return f"Added: {book.title}"
def register_member(self, member):
"""Register a new member"""
if member.member_id in self.members:
return f"Member {member.member_id} already registered"
self.members[member.member_id] = member
return f"Registered: {member.name}"
def borrow_book(self, member_id, isbn):
"""Process book borrowing"""
# Validation
if member_id not in self.members:
return "Member not found"
if isbn not in self.books:
return "Book not found"
member = self.members[member_id]
book = self.books[isbn]
# Check availability
if not book.is_available:
return f"'{book.title}' is currently borrowed"
# Check member limit
if not member.can_borrow():
return f"{member.name} has reached borrowing limit (3 books)"
# Process borrowing
book.is_available = False
book.borrowed_by = member_id
book.due_date = (datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
member.borrowed_books.append(isbn)
return f"{member.name} borrowed '{book.title}' (due: {book.due_date})"
def return_book(self, member_id, isbn):
"""Process book return"""
if member_id not in self.members:
return "Member not found"
if isbn not in self.books:
return "Book not found"
member = self.members[member_id]
book = self.books[isbn]
if book.is_available:
return f"'{book.title}' was not borrowed"
if isbn not in member.borrowed_books:
return f"{member.name} did not borrow this book"
# Process return
book.is_available = True
book.borrowed_by = None
book.due_date = None
member.borrowed_books.remove(isbn)
return f"{member.name} returned '{book.title}'"
def search_books(self, query):
"""Search books by title or author"""
results = []
query_lower = query.lower()
for book in self.books.values():
if (query_lower in book.title.lower() or
query_lower in book.author.lower()):
results.append(book)
return results
def get_available_books(self):
"""Get all available books"""
return [book for book in self.books.values() if book.is_available]
def get_member_books(self, member_id):
"""Get books borrowed by a member"""
if member_id not in self.members:
return []
member = self.members[member_id]
return [self.books[isbn] for isbn in member.borrowed_books]
def generate_report(self):
"""Generate library statistics"""
total_books = len(self.books)
available_books = len(self.get_available_books())
borrowed_books = total_books - available_books
total_members = len(self.members)
report = f"\n{'='*50}\n"
report += f"LIBRARY REPORT: {self.name}\n"
report += f"{'='*50}\n"
report += f"Total Books: {total_books}\n"
report += f"Available: {available_books}\n"
report += f"Borrowed: {borrowed_books}\n"
report += f"Total Members: {total_members}\n"
report += f"{'='*50}\n"
return report
def load_books_from_csv(self, filename):
"""Load books from CSV file"""
count = 0
try:
with open(filename, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
book = Book(
row['isbn'],
row['title'],
row['author'],
int(row['year']),
row['genre']
)
self.add_book(book)
count += 1
return f"Loaded {count} books from {filename}"
except FileNotFoundError:
return f"File {filename} not found"
# Demo the Library Management System
print("\n--- Library System Demo ---")
# Create library
library = Library("City Central Library")
# Load books from CSV
print(library.load_books_from_csv("books.csv"))
# Register members
member1 = Member("M001", "Alice Johnson", "alice@email.com")
member2 = Member("M002", "Bob Smith", "bob@email.com")
print(library.register_member(member1))
print(library.register_member(member2))
# Borrow books
print("\n--- Borrowing Books ---")
print(library.borrow_book("M001", "978-0-1234-5678-0"))
print(library.borrow_book("M001", "978-0-1234-5679-7"))
print(library.borrow_book("M002", "978-0-1234-5680-3"))
# Try to borrow unavailable book
print(library.borrow_book("M002", "978-0-1234-5678-0"))
# Check member's borrowed books
print("\n--- Alice's Borrowed Books ---")
alice_books = library.get_member_books("M001")
for book in alice_books:
print(f" - {book}")
# Return a book
print("\n--- Returning Books ---")
print(library.return_book("M001", "978-0-1234-5678-0"))
# Search books
print("\n--- Search Results for 'Python' ---")
results = library.search_books("Python")
for book in results:
print(f" - {book}")
# Generate report
print(library.generate_report())
print("\n" + "=" * 60)
print("Advanced Session 1 Completed!")
print("Master OOP to build professional applications!")
print("=" * 60)