python
exercises
exercises.py🐍python
"""
09 - OOP: Exercises
Practice object-oriented programming concepts.
"""
print("=" * 60)
print("OOP EXERCISES")
print("=" * 60)
# =============================================================================
# EXERCISE 1: Basic Class
# Create a 'Rectangle' class with width and height attributes
# Add methods: area(), perimeter(), is_square()
# =============================================================================
print("\n--- Exercise 1: Rectangle Class ---")
# Your code here:
class Rectangle:
pass # Replace with your implementation
# Test:
# rect = Rectangle(4, 5)
# print(f"Area: {rect.area()}") # Should print 20
# print(f"Perimeter: {rect.perimeter()}") # Should print 18
# print(f"Is square: {rect.is_square()}") # Should print False
# square = Rectangle(5, 5)
# print(f"Is square: {square.is_square()}") # Should print True
# =============================================================================
# EXERCISE 2: Bank Account with Encapsulation
# Create a BankAccount class with:
# - private balance attribute
# - deposit(amount) method
# - withdraw(amount) method (with balance check)
# - get_balance() method
# =============================================================================
print("\n--- Exercise 2: Bank Account ---")
# Your code here:
# Test:
# account = BankAccount("Alice", 1000)
# print(account.deposit(500)) # Should return True
# print(account.get_balance()) # Should print 1500
# print(account.withdraw(2000)) # Should return False (insufficient)
# =============================================================================
# EXERCISE 3: Inheritance - Vehicles
# Create a Vehicle base class with make, model, year
# Create Car and Motorcycle subclasses
# Car should have num_doors, Motorcycle should have has_sidecar
# Each should have a description() method
# =============================================================================
print("\n--- Exercise 3: Vehicle Inheritance ---")
# Your code here:
# Test:
# car = Car("Toyota", "Camry", 2022, 4)
# bike = Motorcycle("Harley", "Sportster", 2021, False)
# print(car.description())
# print(bike.description())
# =============================================================================
# EXERCISE 4: Polymorphism - Shapes
# Create Shape base class with abstract area() method
# Create Circle, Rectangle, Triangle subclasses
# Create a function that calculates total area of any shapes list
# =============================================================================
print("\n--- Exercise 4: Polymorphism ---")
from abc import ABC, abstractmethod
# Your code here:
# Test:
# shapes = [Circle(5), Rectangle(4, 6), Triangle(3, 4)]
# print(f"Total area: {total_area(shapes)}")
# =============================================================================
# EXERCISE 5: Magic Methods - Fraction Class
# Create a Fraction class that supports:
# - __str__ for display
# - __add__ for addition
# - __mul__ for multiplication
# - __eq__ for equality comparison
# =============================================================================
print("\n--- Exercise 5: Fraction Class ---")
# Your code here:
# Test:
# f1 = Fraction(1, 2)
# f2 = Fraction(1, 4)
# print(f1) # Should print "1/2"
# print(f1 + f2) # Should print "3/4"
# print(f1 * f2) # Should print "1/8"
# print(f1 == Fraction(2, 4)) # Should print True
# =============================================================================
# EXERCISE 6: Property Decorator - Person
# Create a Person class with:
# - first_name and last_name properties
# - full_name computed property
# - age property with validation (must be positive)
# - email property with basic validation
# =============================================================================
print("\n--- Exercise 6: Properties ---")
# Your code here:
# Test:
# person = Person("John", "Doe", 25, "john@example.com")
# print(person.full_name) # John Doe
# person.age = -5 # Should raise ValueError
# =============================================================================
# EXERCISE 7: Class Methods - Factory Pattern
# Create a Date class with day, month, year
# Add class methods:
# - from_string(date_string) - parse "DD-MM-YYYY"
# - today() - return today's date
# =============================================================================
print("\n--- Exercise 7: Class Methods ---")
from datetime import date
# Your code here:
# Test:
# d1 = Date.from_string("25-12-2023")
# print(d1) # Date: 25-12-2023
# d2 = Date.today()
# print(d2)
# =============================================================================
# EXERCISE 8: Static Methods - Validator
# Create a Validator class with static methods:
# - is_email(string) - check if valid email format
# - is_phone(string) - check if valid phone format
# - is_password_strong(string) - check password strength
# =============================================================================
print("\n--- Exercise 8: Static Methods ---")
# Your code here:
# Test:
# print(Validator.is_email("test@example.com")) # True
# print(Validator.is_email("invalid")) # False
# print(Validator.is_password_strong("Str0ng!Pass")) # True
# =============================================================================
# EXERCISE 9: Composition - Library System
# Create these classes:
# - Book(title, author, isbn)
# - Member(name, member_id)
# - Library that manages books and members
# Library should have: add_book, add_member, borrow_book, return_book
# =============================================================================
print("\n--- Exercise 9: Library System ---")
# Your code here:
# Test:
# library = Library("City Library")
# book = Book("Python 101", "Author", "12345")
# member = Member("Alice", "M001")
# library.add_book(book)
# library.add_member(member)
# library.borrow_book("M001", "12345")
# =============================================================================
# EXERCISE 10: Iterator Class
# Create a Fibonacci iterator class that generates
# Fibonacci numbers up to a maximum value
# =============================================================================
print("\n--- Exercise 10: Iterator ---")
# Your code here:
# Test:
# for num in Fibonacci(100):
# print(num, end=" ")
# Should print: 0 1 1 2 3 5 8 13 21 34 55 89
# =============================================================================
# SOLUTIONS (scroll down)
# =============================================================================
print("\n\n" + "=" * 60)
print("SOLUTIONS")
print("=" * 60)
# SOLUTION 1
print("\n--- Solution 1: Rectangle ---")
class RectangleSol:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
def is_square(self):
return self.width == self.height
rect = RectangleSol(4, 5)
print(f"Area: {rect.area()}")
print(f"Perimeter: {rect.perimeter()}")
print(f"Is square: {rect.is_square()}")
# SOLUTION 2
print("\n--- Solution 2: Bank Account ---")
class BankAccountSol:
def __init__(self, owner, balance=0):
self.owner = owner
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return True
return False
def get_balance(self):
return self.__balance
account = BankAccountSol("Alice", 1000)
print(f"Deposit 500: {account.deposit(500)}")
print(f"Balance: {account.get_balance()}")
print(f"Withdraw 2000: {account.withdraw(2000)}")
# SOLUTION 3
print("\n--- Solution 3: Vehicles ---")
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f"{self.year} {self.make} {self.model}"
class Car(Vehicle):
def __init__(self, make, model, year, num_doors):
super().__init__(make, model, year)
self.num_doors = num_doors
def description(self):
return f"{super().description()} ({self.num_doors} doors)"
class Motorcycle(Vehicle):
def __init__(self, make, model, year, has_sidecar):
super().__init__(make, model, year)
self.has_sidecar = has_sidecar
def description(self):
sidecar = "with sidecar" if self.has_sidecar else "no sidecar"
return f"{super().description()} ({sidecar})"
car = Car("Toyota", "Camry", 2022, 4)
bike = Motorcycle("Harley", "Sportster", 2021, False)
print(car.description())
print(bike.description())
# SOLUTION 4
print("\n--- Solution 4: Polymorphism ---")
class ShapeSol(ABC):
@abstractmethod
def area(self):
pass
class CircleSol(ShapeSol):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * self.radius ** 2
class RectangleSol2(ShapeSol):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class TriangleSol(ShapeSol):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
def total_area(shapes):
return sum(shape.area() for shape in shapes)
shapes = [CircleSol(5), RectangleSol2(4, 6), TriangleSol(3, 4)]
print(f"Total area: {total_area(shapes):.2f}")
# SOLUTION 5
print("\n--- Solution 5: Fraction ---")
from math import gcd
class Fraction:
def __init__(self, numerator, denominator):
common = gcd(numerator, denominator)
self.numerator = numerator // common
self.denominator = denominator // common
def __str__(self):
return f"{self.numerator}/{self.denominator}"
def __add__(self, other):
num = self.numerator * other.denominator + other.numerator * self.denominator
den = self.denominator * other.denominator
return Fraction(num, den)
def __mul__(self, other):
return Fraction(
self.numerator * other.numerator,
self.denominator * other.denominator
)
def __eq__(self, other):
return self.numerator == other.numerator and self.denominator == other.denominator
f1 = Fraction(1, 2)
f2 = Fraction(1, 4)
print(f"f1: {f1}")
print(f"f1 + f2: {f1 + f2}")
print(f"f1 * f2: {f1 * f2}")
print(f"f1 == Fraction(2, 4): {f1 == Fraction(2, 4)}")
# SOLUTION 10
print("\n--- Solution 10: Fibonacci Iterator ---")
class Fibonacci:
def __init__(self, max_value):
self.max_value = max_value
def __iter__(self):
self.a = 0
self.b = 1
return self
def __next__(self):
if self.a > self.max_value:
raise StopIteration
current = self.a
self.a, self.b = self.b, self.a + self.b
return current
print("Fibonacci up to 100:")
for num in Fibonacci(100):
print(num, end=" ")
print()
print("\n" + "=" * 60)
print("END OF EXERCISES")
print("=" * 60)