Skip to content

Practical Exercises: Solving Real-World Problems Using Object-Oriented Programming in Python

Updated: at 05:01 AM

Object-oriented programming (OOP) is a programming paradigm that models real-world entities as objects and defines their attributes and behaviors within classes. Practicing OOP principles through hands-on exercises is crucial for mastering Python and building robust, reusable code to solve complex problems. This guide provides practical examples and coding exercises to reinforce core OOP concepts like classes, objects, inheritance, encapsulation, and polymorphism while developing solutions for real-world scenarios.

Table of Contents

Open Table of Contents

An Overview of Object-Oriented Programming

OOP models problems as systems of interacting objects rather than a sequence of procedural steps. Each object encapsulates related data and behaviors defined in its class. The key principles of OOP include:

Proper object modeling requires analyzing problems, identifying key entities, defining classes, and determining relationships between classes. OOP promotes modularity, reusability, and maintainability in large programs.

Let’s examine some practical OOP exercises in Python.

Exercise 1: Modeling a Bank Account

Financial applications commonly use OOP principles. This exercise models a simple bank account as a Python class.

First, identify the attributes and behaviors of a bank account:

Next, define a BankAccount class with an initializer taking account number, name, and initial deposit as parameters. Include methods to deposit, withdraw, and check balances:

class BankAccount:

    def __init__(self, account_number, name, balance=0):
        self.account_number = account_number
        self.name = name
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if self.balance >= amount:
            self.balance -= amount
        else:
            print("Insufficient funds")

    def check_balance(self):
        print(f"Balance: {self.balance}")

This class encapsulates the data and behaviors of a bank account. Let’s create some objects:

acct1 = BankAccount("1234", "John Doe", 500)
acct2 = BankAccount("2345", "Jane Doe")

acct1.deposit(100)
acct1.check_balance() # Balance: 600

acct2.withdraw(200) # Insufficient funds

This exercise demonstrates core OOP principles like encapsulation, abstraction, and polymorphism in a real banking application. The BankAccount class bundles data and functions, hiding internal details from objects. Custom objects like acct1 and acct2 can use methods polymorphically despite having different balances.

Exercise 2: Modeling Students and Courses

OOP is commonly used in academic systems to model students, courses, grades, etc. This exercise builds classes for students and courses.

First, identify attributes and behaviors:

Student

Course

Next, define Student and Course classes:

class Student:

    def __init__(self, name, id):
        self.name = name
        self.id = id
        self.courses_taken = []

    def enroll(self, course):
        self.courses_taken.append(course)

    def drop(self, course):
        self.courses_taken.remove(course)

    def view_courses(self):
        print(f"{self.name}'s courses: {self.courses_taken}")

class Course:

    def __init__(self, title, instructor, max_students):
        self.title = title
        self.instructor = instructor
        self.students = []
        self.max_students = max_students

    def add_student(self, student):
        if len(self.students) < self.max_students:
            self.students.append(student)
            student.enroll(self)
        else:
            print("Course is full")

    def drop_student(self, student):
        student.drop(self)
        self.students.remove(student)

    def view_students(self):
        print(f"Students in {self.title}: {self.students}")

Now create some objects:

math101 = Course("Calculus", "Dr. Smith", 3)
john = Student("John Doe", "12345")
jane = Student("Jane Doe", "67890")

math101.add_student(john)
math101.add_student(jane)

john.view_courses()
# John Doe's courses: [Calculus]

math101.view_students()
# Students in Calculus: [John Doe, Jane Doe]

This models a real academic system using OOP. Encapsulation binds student and course data/functions together. Inheritance or abstraction could improve the design further. The classes are reused to model different objects polymorphically.

Exercise 3: Building an GUI Quiz Application

OOP is very useful for developing graphical applications. This exercise builds a multiple choice quiz app with a GUI using Python’s tkinter module and OOP principles.

First, import tkinter and create the main window:

import tkinter as tk

window = tk.Tk()
window.geometry("600x400")
window.title("Math Quiz")

Next, create a Quiz class to handle the quiz logic and GUI components:

class Quiz:

    def __init__(self):

        # Quiz attributes
        self.questions = {
            1:["What is 2 + 4?", "5", "7", "6", "B"],
            2:["What is 10 - 9?", "1", "3", "2", "A"]
        }
        self.score = 0

        # GUI widgets
        self.question_label = tk.Label(window, text="")
        self.option_buttons = []
        for i in range(4):
            btn = tk.Button(window, text="")
            self.option_buttons.append(btn)

        self.display_question()

    def display_question(self):
        # Display current question and options
        q_text, *options = self.questions[self.current_question]
        self.question_label.config(text=q_text)
        for i, option in enumerate(options):
            self.option_buttons[i].config(text=option)

    def check_answer(self, user_choice):
        # Check if user choice matches answer
        answer = self.questions[self.current_question][4]
        if user_choice == answer:
            # Update score if correct
            self.score += 1
        # Load next question
        self.current_question += 1
        if self.current_question <= len(self.questions):
            self.display_question()
        else:
            print("Quiz over!")
            print(f"Final score: {self.score}")

The Quiz class encapsulates the quiz data, manages the GUI, and handles user interaction logic. Create a Quiz object to launch the app:

quiz = Quiz()
window.mainloop()

This exercise demonstrates using OOP to build a real-world GUI application in Python. The object-oriented design promotes organized, modular, and reusable code.

Exercise 4: Building a Turn-Based Strategy Game

OOP is commonly used in game development. This exercise builds a basic turn-based strategy game in Python using OOP principles.

The game has a map with different kinds of tiles. Each player has a team of characters that can move and perform actions on the map.

First, define MapTile and Character parent classes:

class MapTile:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Character:
    def __init__(self, name, health, attack, defense):
        self.name = name
        self.health = health
        self.attack = attack
        self.defense = defense

    def move(self, dx, dy):
        self.x += dx
        self.y += dy

    def is_alive(self):
        return self.health > 0

Next, create child classes for specific tile and character types:

class Plains(MapTile): pass

class Forest(MapTile):
    def __init__(self, x, y):
        super().__init__(x, y)

class Warrior(Character):
    def attack(self, enemy):
        damage = self.attack - enemy.defense
        enemy.health -= damage

class Archer(Character):
    def ranged_attack(self, enemy):
        damage = self.attack - enemy.defense
        enemy.health -= damage

The child classes inherit from the parents but add unique attributes and behaviors.

Finally, build the game loop:

map = [
    [Plains(0,0), Forest(1,0), Plains(2,0)],
    [Forest(0,1), Plains(1,1), Plains(2,1)],
    [Plains(0,2), Plains(1,2), Plains(2,2)]
]

warrior = Warrior("Jon", 100, 20, 10)
archer = Archer("Arya", 80, 15, 5)

while True:
    # Handle player actions
    warrior.move(1, 0)
    archer.ranged_attack(warrior)

    # Enemy actions

    if not warrior.is_alive():
        print("Game over!")
        break

This builds a basic turn-based game with custom tile and character classes. More features like new actions, AI opponents, multiplayer etc. can be added by leveraging OOP principles like polymorphism and inheritance.

Key Takeaways

Practical OOP exercises like these are great for mastering Python classes, objects, and other core principles. When tackling programming problems:

Regular practice with increasingly complex examples develops strong OOP skills transferable to any large Python project.

Conclusion

Object-oriented programming is invaluable for modeling complex real-world systems in Python and crafting maintainable, robust code. This guide provided diverse examples and exercises for practicing core OOP concepts like encapsulation, inheritance, and polymorphism while solving practical problems. Readers should now feel prepared to start incorporating object-oriented principles in their own Python programming.