Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

© 2026 rakrisi Daily

Classes and Objects - Your First OOP Steps

Classes and Objects: Your First OOP Steps

Welcome to Classes and Objects! Think of a class as a blueprint for a house, and objects as the actual houses built from that blueprint. Let’s start building!

What Are Classes and Objects?

The Blueprint Analogy

# Class = Blueprint
class House:
    def __init__(self, color, rooms):
        self.color = color
        self.rooms = rooms

# Objects = Actual houses
blue_house = House("blue", 3)      # One house
red_house = House("red", 4)        # Another house
green_house = House("green", 2)    # Third house

print(f"Blue house: {blue_house.color} with {blue_house.rooms} rooms")
print(f"Red house: {red_house.color} with {red_house.rooms} rooms")

Real-World Example: Users

class User:
    """A simple User class."""

    def __init__(self, name, email):
        self.name = name
        self.email = email

    def greet(self):
        return f"Hello, I'm {self.name}!"

# Create user objects
alice = User("Alice", "alice@example.com")
bob = User("Bob", "bob@example.com")

print(alice.greet())  # "Hello, I'm Alice!"
print(bob.greet())    # "Hello, I'm Bob!"

print(alice.name)     # "Alice"
print(bob.email)      # "bob@example.com"

The __init__ Method

Constructor Basics

class Car:
    def __init__(self, make, model, year):
        """Initialize a new Car object."""
        self.make = make      # Instance variable
        self.model = model    # Instance variable
        self.year = year      # Instance variable
        self.mileage = 0     # Default value

# Create car objects
car1 = Car("Toyota", "Camry", 2020)
car2 = Car("Honda", "Civic", 2019)

print(f"{car1.year} {car1.make} {car1.model}")  # "2020 Toyota Camry"
print(f"Mileage: {car1.mileage}")              # "Mileage: 0"

Default Parameters

class Book:
    def __init__(self, title, author, pages=100, genre="Fiction"):
        self.title = title
        self.author = author
        self.pages = pages
        self.genre = genre
        self.is_read = False

# Create books with different parameters
book1 = Book("1984", "George Orwell", 328, "Dystopian")
book2 = Book("The Hobbit", "J.R.R. Tolkien")  # Uses defaults

print(f"{book1.title} by {book1.author} - {book1.pages} pages")
print(f"{book2.title} by {book2.author} - {book2.pages} pages, {book2.genre}")

Instance Methods

Methods That Work with Object Data

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        """Add money to the account."""
        if amount > 0:
            self.balance += amount
            print(f"Deposited ${amount}. New balance: ${self.balance}")
        else:
            print("Deposit amount must be positive")

    def withdraw(self, amount):
        """Remove money from the account."""
        if amount > 0 and amount <= self.balance:
            self.balance -= amount
            print(f"Withdrew ${amount}. New balance: ${self.balance}")
        elif amount > self.balance:
            print("Insufficient funds")
        else:
            print("Withdrawal amount must be positive")

    def get_balance(self):
        """Return current balance."""
        return self.balance

# Create and use a bank account
account = BankAccount("Alice", 1000)

account.deposit(500)      # Deposited $500. New balance: $1500
account.withdraw(200)     # Withdrew $200. New balance: $1300
account.withdraw(2000)    # Insufficient funds

print(f"Final balance: ${account.get_balance()}")

Methods Calling Other Methods

class EmailClient:
    def __init__(self, username):
        self.username = username
        self.inbox = []
        self.sent = []

    def send_email(self, to, subject, body):
        """Send an email."""
        email = {
            "to": to,
            "subject": subject,
            "body": body,
            "from": self.username
        }

        self.sent.append(email)
        print(f"Email sent to {to}: {subject}")

        # Simulate sending (in real app, this would connect to server)
        self._log_activity(f"Sent email to {to}")

    def receive_email(self, from_addr, subject, body):
        """Receive an email."""
        email = {
            "from": from_addr,
            "subject": subject,
            "body": body
        }

        self.inbox.append(email)
        print(f"Email received from {from_addr}: {subject}")

        self._log_activity(f"Received email from {from_addr}")

    def _log_activity(self, message):
        """Private method to log activity."""
        print(f"[LOG] {self.username}: {message}")

# Test email client
client = EmailClient("alice@example.com")

client.send_email("bob@example.com", "Hello!", "How are you?")
client.receive_email("charlie@example.com", "Meeting", "See you tomorrow")

The self Parameter

Why self Matters

class Counter:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1

    def get_count(self):
        return self.count

# Without self - THIS WON'T WORK
class BadCounter:
    def __init__(self):
        count = 0  # This creates a local variable, not an instance variable

    def increment(self):
        count += 1  # This also creates a local variable

    def get_count(self):
        return count  # NameError - count not defined

# Test
good_counter = Counter()
good_counter.increment()
good_counter.increment()
print(good_counter.get_count())  # 2

bad_counter = BadCounter()
# bad_counter.increment()  # Would cause UnboundLocalError

self in Different Contexts

class Person:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Hello, I'm {self.name}"

    def introduce(self, other_person):
        return f"{self.name} meets {other_person.name}"

# Create people
alice = Person("Alice")
bob = Person("Bob")

print(alice.greet())              # "Hello, I'm Alice"
print(bob.greet())                # "Hello, I'm Bob"

print(alice.introduce(bob))       # "Alice meets Bob"
print(bob.introduce(alice))       # "Bob meets Alice"

Class vs Instance Variables

Instance Variables (Unique to Each Object)

class Student:
    def __init__(self, name, grade):
        self.name = name        # Instance variable
        self.grade = grade      # Instance variable
        self.scores = []        # Instance variable

    def add_score(self, score):
        self.scores.append(score)

# Each student has their own data
alice = Student("Alice", "10th")
bob = Student("Bob", "10th")

alice.add_score(95)
alice.add_score(87)
bob.add_score(92)

print(f"Alice's scores: {alice.scores}")  # [95, 87]
print(f"Bob's scores: {bob.scores}")      # [92]

Class Variables (Shared by All Objects)

class Student:
    school_name = "Python High School"  # Class variable
    total_students = 0                  # Class variable

    def __init__(self, name, grade):
        self.name = name
        self.grade = grade
        Student.total_students += 1     # Modify class variable

# All students share the same school
alice = Student("Alice", "10th")
bob = Student("Bob", "11th")

print(alice.school_name)    # "Python High School"
print(bob.school_name)      # "Python High School"

print(Student.total_students)  # 2

# Changing class variable affects all instances
Student.school_name = "Advanced Python Academy"
print(alice.school_name)    # "Advanced Python Academy"
print(bob.school_name)      # "Advanced Python Academy"

Practical Examples

Example 1: Todo List

class TodoList:
    def __init__(self, owner):
        self.owner = owner
        self.tasks = []

    def add_task(self, description, priority="medium"):
        """Add a new task."""
        task = {
            "description": description,
            "priority": priority,
            "completed": False
        }
        self.tasks.append(task)
        print(f"Added task: {description}")

    def complete_task(self, index):
        """Mark a task as completed."""
        if 0 <= index < len(self.tasks):
            self.tasks[index]["completed"] = True
            print(f"Completed: {self.tasks[index]['description']}")
        else:
            print("Invalid task index")

    def show_tasks(self):
        """Display all tasks."""
        if not self.tasks:
            print("No tasks in the list")
            return

        print(f"\n{self.owner}'s Todo List:")
        for i, task in enumerate(self.tasks):
            status = "" if task["completed"] else ""
            print(f"{i}. {status} {task['description']} ({task['priority']})")

    def get_pending_tasks(self):
        """Return count of pending tasks."""
        return sum(1 for task in self.tasks if not task["completed"])

# Test todo list
my_todos = TodoList("Alice")

my_todos.add_task("Learn Python classes", "high")
my_todos.add_task("Practice OOP", "medium")
my_todos.add_task("Build a project", "low")

my_todos.show_tasks()

my_todos.complete_task(0)
my_todos.complete_task(1)

print(f"\nPending tasks: {my_todos.get_pending_tasks()}")
my_todos.show_tasks()

Example 2: Simple Game Character

class GameCharacter:
    def __init__(self, name, health=100, attack_power=10):
        self.name = name
        self.health = health
        self.max_health = health
        self.attack_power = attack_power
        self.level = 1
        self.experience = 0

    def attack(self, target):
        """Attack another character."""
        damage = self.attack_power
        target.take_damage(damage)
        print(f"{self.name} attacks {target.name} for {damage} damage!")

    def take_damage(self, damage):
        """Take damage from an attack."""
        self.health -= damage
        if self.health <= 0:
            self.health = 0
            print(f"{self.name} has been defeated!")
        else:
            print(f"{self.name} has {self.health} health remaining")

    def heal(self, amount):
        """Heal the character."""
        old_health = self.health
        self.health = min(self.max_health, self.health + amount)
        healed = self.health - old_health
        print(f"{self.name} healed for {healed} health")

    def gain_experience(self, exp):
        """Gain experience and level up if needed."""
        self.experience += exp
        print(f"{self.name} gained {exp} experience!")

        # Level up every 100 experience
        while self.experience >= self.level * 100:
            self.level_up()

    def level_up(self):
        """Level up the character."""
        self.level += 1
        self.max_health += 20
        self.health = self.max_health  # Full heal on level up
        self.attack_power += 5
        print(f"{self.name} leveled up to level {self.level}!")

    def __str__(self):
        """String representation of the character."""
        return f"{self.name} (Level {self.level}) - HP: {self.health}/{self.max_health}"

# Test game characters
hero = GameCharacter("Hero", 120, 15)
goblin = GameCharacter("Goblin", 80, 8)

print(hero)
print(goblin)
print()

# Combat
hero.attack(goblin)
goblin.attack(hero)
hero.heal(30)
hero.gain_experience(150)  # Should level up

print()
print(hero)
print(goblin)

Example 3: Library Book System

class Book:
    def __init__(self, title, author, isbn):
        self.title = title
        self.author = author
        self.isbn = isbn
        self.is_available = True
        self.borrower = None

    def borrow(self, borrower_name):
        """Borrow the book."""
        if self.is_available:
            self.is_available = False
            self.borrower = borrower_name
            print(f"'{self.title}' borrowed by {borrower_name}")
            return True
        else:
            print(f"'{self.title}' is already borrowed by {self.borrower}")
            return False

    def return_book(self):
        """Return the book."""
        if not self.is_available:
            print(f"'{self.title}' returned by {self.borrower}")
            self.is_available = True
            self.borrower = None
            return True
        else:
            print(f"'{self.title}' is not currently borrowed")
            return False

    def __str__(self):
        status = "Available" if self.is_available else f"Borrowed by {self.borrower}"
        return f"'{self.title}' by {self.author} - {status}"

class Library:
    def __init__(self, name):
        self.name = name
        self.books = []

    def add_book(self, book):
        """Add a book to the library."""
        self.books.append(book)
        print(f"Added '{book.title}' to {self.name}")

    def find_book(self, title):
        """Find a book by title."""
        for book in self.books:
            if book.title.lower() == title.lower():
                return book
        return None

    def show_available_books(self):
        """Show all available books."""
        available = [book for book in self.books if book.is_available]
        if available:
            print(f"\nAvailable books at {self.name}:")
            for book in available:
                print(f"  - {book}")
        else:
            print(f"No books available at {self.name}")

# Test library system
library = Library("City Library")

# Add books
book1 = Book("1984", "George Orwell", "123456")
book2 = Book("To Kill a Mockingbird", "Harper Lee", "234567")
book3 = Book("The Great Gatsby", "F. Scott Fitzgerald", "345678")

library.add_book(book1)
library.add_book(book2)
library.add_book(book3)

# Borrow and return books
book1.borrow("Alice")
book2.borrow("Bob")
book1.borrow("Charlie")  # Should fail

library.show_available_books()

book1.return_book()
library.show_available_books()

Practice Exercises

Exercise 1: Student Grade System

Create a Student class that:

  • Stores name, student ID, and grades
  • Has methods to add grades, calculate average
  • Can determine if student is passing (average >= 70)

Exercise 2: Bank Account Manager

Build a BankAccount class with:

  • Deposit, withdraw, and check balance methods
  • Account number and owner name
  • Transaction history
  • Overdraft protection

Exercise 3: Simple Shopping Cart

Create a shopping cart system with:

  • Product class (name, price, quantity)
  • ShoppingCart class (add items, remove items, calculate total)
  • Apply discount functionality

Exercise 4: Digital Library

Build a digital library with:

  • EBook class (title, author, file size)
  • Library class (add books, search by author/title, track downloads)
  • Reading progress tracking

Exercise 5: Game Inventory System

Create a game inventory with:

  • Item class (name, description, value)
  • Inventory class (add/remove items, calculate total value)
  • Equipment system (equip/unequip items)

Summary

Classes and objects are the foundation of OOP:

Class Definition:

class ClassName:
    def __init__(self, parameters):
        self.attribute = value

Creating Objects:

object = ClassName(arguments)

Instance Methods:

def method_name(self, parameters):
    # Method body
    return result

Key Concepts:

  • __init__ is the constructor
  • self refers to the current object
  • Instance variables are unique to each object
  • Class variables are shared by all objects
  • Methods define object behavior

Next: Encapsulation - protecting your object’s data! 🔒