Day 13: Introduction to Object-Oriented Programming — Classes & Objects

🐍 Day 13: Introduction to Object-Oriented Programming — Classes & Objects


1. Learning Objectives

By the end of Day 13, you will be able to:

  • Understand what Object-Oriented Programming (OOP) is and why it matters
  • Define your own classes to create custom data types
  • Use the __init__ method to initialize object attributes
  • Differentiate between instance attributes and class attributes
  • Create objects (instances) from a class and call their methods
  • Read and write code that models real-world entities as classes
  • Recognize the self parameter and how it works

2. Concept Explanation

2.1 Why Object-Oriented Programming? — From Functions to Blueprints

So far, you've organised code into functions and modules — great for reuse. But as programs grow, managing related data and behaviour with plain dictionaries and lists becomes messy.

OOP bundles data (attributes) and behaviour (methods) into a single structure called an object. Think of a class as a blueprint and an object as the thing you build from that blueprint.

Real-World AnalogyPython OOP
Blueprint of a houseclass
Actual houses built from itObjects (instances)
Features: colour, number of roomsAttributes (data)
Actions: open door, turn on lightsMethods (functions inside class)

Using OOP, you can model a BankAccount, a Student, a Car — anything with properties and behaviour — in clean, reusable code.


2.2 Defining a Class — The class Keyword

A class is defined with the class keyword, followed by a name (PascalCase) and a colon. The body contains methods (functions) and attributes.

class Dog:
    """A simple Dog class."""

    # The __init__ method (constructor) runs when a new Dog is created
    def __init__(self, name, age):
        # self refers to the specific instance being created
        self.name = name   # instance attribute
        self.age = age

    # A method: a function that belongs to the class
    def bark(self):
        print(f"{self.name} says Woof!")

    def birthday(self):
        self.age += 1
        print(f"Happy birthday {self.name}! You are now {self.age}.")

2.3 __init__ — The Constructor

__init__ is a special method called automatically when you create a new instance. It sets up the object's initial state.

  • The first parameter is always self (you can name it anything, but self is the universal convention).
  • self refers to the instance that is being created or used.

2.4 Creating Objects (Instances)

You create an object by calling the class like a function:

# Create two different Dog objects
my_dog = Dog("Rex", 3)
your_dog = Dog("Bella", 1)

# Access attributes using dot notation
print(my_dog.name)   # Rex
print(your_dog.age)  # 1

# Call methods
my_dog.bark()        # Rex says Woof!
your_dog.birthday()  # Happy birthday Bella! You are now 2.

Each object has its own copy of instance attributes. my_dog and your_dog are independent.


2.5 Instance vs. Class Attributes

  • Instance attributes are defined inside __init__ with self. — each object has its own value.
  • Class attributes are defined directly inside the class body, shared by all instances.
class Student:
    school = "Python University"   # Class attribute

    def __init__(self, name, grade):
        self.name = name            # Instance attribute
        self.grade = grade

s1 = Student("Alice", 85)
s2 = Student("Bob", 92)

print(s1.school)   # Python University (shared)
print(s2.school)   # Python University

# Change class attribute for all
Student.school = "Code Academy"
print(s1.school)   # Code Academy
print(s2.school)   # Code Academy

2.6 Methods — Functions Inside a Class

Methods are functions that belong to a class and usually operate on instance data. The first parameter is always self.

class Rectangle:
    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)

r = Rectangle(5, 3)
print(r.area())       # 15
print(r.perimeter())  # 16

Methods can also take additional parameters after self.


2.7 The self Parameter Explained

self is not a keyword but a universally used convention. It refers to the current instance, allowing you to access its attributes and other methods.

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

    def increment(self):
        self.count += 1   # Accesses instance attribute

    def get_count(self):
        return self.count

When you call obj.method(), Python automatically passes obj as the first argument (self).


2.8 Common Mistakes

MistakeWhy It Happens
Forgetting self as first parameter in methodTypeError: method() takes 0 positional arguments but 1 was given
Calling a method without parenthesesr.area returns the method object, doesn't run it
Using class name instead of instanceDog.bark() fails; you need an instance: my_dog.bark()
Confusing class and instance attributesModifying obj.class_attr creates an instance attribute, doesn't change class attr

3. Code Examples

Example 1: Bank Account Class

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

    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            print(f"Deposited ${amount:.2f}. New balance: ${self.balance:.2f}")
        else:
            print("Amount must be positive.")

    def withdraw(self, amount):
        if 0 < amount <= self.balance:
            self.balance -= amount
            print(f"Withdrew ${amount:.2f}. New balance: ${self.balance:.2f}")
        else:
            print("Invalid amount or insufficient funds.")

    def display(self):
        print(f"Account owner: {self.owner}, Balance: ${self.balance:.2f}")

acc = BankAccount("Alice", 1000)
acc.display()
acc.deposit(250)
acc.withdraw(300)

Example 2: Student Grade Tracker

class Student:
    def __init__(self, name):
        self.name = name
        self.grades = []

    def add_grade(self, grade):
        self.grades.append(grade)

    def average(self):
        if not self.grades:
            return 0
        return sum(self.grades) / len(self.grades)

    def __str__(self):
        return f"{self.name} - Grades: {self.grades}, Average: {self.average():.2f}"

s = Student("Bob")
s.add_grade(85)
s.add_grade(92)
print(s)

Example 3: Class Attribute Counter

class Employee:
    company = "TechCorp"
    total_employees = 0   # class-level counter

    def __init__(self, name):
        self.name = name
        Employee.total_employees += 1

    def __del__(self):   # called when object is deleted (rarely needed)
        Employee.total_employees -= 1

e1 = Employee("Alice")
e2 = Employee("Bob")
print(Employee.total_employees)  # 2

4. Hands-On Exercises

Exercise 1: Basic Class Creation

Create a Book class with attributes title, author, and pages. Write a method info() that returns a string like "Title: Python 101, Author: Guido, Pages: 300". Create two book objects and print their info.

Exercise 2: Rectangle Class

Define a Rectangle class with attributes width and height. Add methods area() and perimeter(). Create an instance and print both area and perimeter.

Exercise 3: Temperature Converter Class

Create a Temperature class that stores a temperature in Celsius. Add methods to_fahrenheit() (returns celsius * 9/5 + 32) and to_kelvin() (returns celsius + 273.15). Test with 25°C.

Exercise 4: Shopping Cart

Build a ShoppingCart class. It should maintain a list of items (strings). Methods: add_item(item), remove_item(item), view_cart(), and clear_cart(). Test all operations.

Exercise 5: Class vs Instance Attribute Experiment

Create a Car class with a class attribute wheels = 4 and instance attributes make and model. Create two cars. Print Car.wheels and car1.wheels. Then change car1.wheels = 3 — what happens to car2.wheels and Car.wheels? Explain.


5. Applied Challenge Task 🏗️

Library Management System

Design a simple library system using OOP. Create three classes:

Book class:

  • Attributes: title, author, isbn, is_available (default True)
  • Methods: borrow() (set is_available to False, print confirmation), return_book() (set to True), __str__() returns book info and availability

Member class:

  • Attributes: name, member_id, borrowed_books (list)
  • Methods: borrow(book) — if book is available, borrow it and add to list. If not, print message. return_book(book) — remove from list, mark book as available. list_borrowed() — print borrowed books.

Library class:

  • Attributes: books (list of Book objects), members (list of Member objects)
  • Methods: add_book(book), register_member(member), find_book_by_title(title) returning Book or None, display_available_books()

Then write a small menu-driven program to test the system: add books, register members, borrow/return books, list available books.

Example usage:

Library Menu:
1. Add Book
2. Register Member
3. Borrow Book
4. Return Book
5. Show Available Books
6. Show Member Borrowed Books
7. Exit

Stretch goals:

  • Add a simple ID generation for members
  • Prevent borrowing if member already has 3 books
  • Save/Load library data using JSON and file I/O (from Days 9/12)

6. Brief Review Summary

ConceptKey Points
OOPBundles data and behaviour into objects
ClassBlueprint defined with class keyword
ObjectInstance of a class, created by calling the class
__init__Constructor — initialises instance attributes
selfRefers to the current instance (first parameter of methods)
Instance attributesUnique to each object, set with self.
Class attributesShared by all instances, defined outside __init__
MethodsFunctions inside a class, first parameter is self
Dot notationobject.attribute or object.method()

7. Preview of Next Topic — Day 14

Tomorrow we deepen OOP with the three pillars:

  • Inheritance — creating child classes that reuse and extend parent behaviour
  • Encapsulation — controlling access to attributes (private/public conventions)
  • Polymorphism — different classes sharing the same interface
  • Method overriding and super()

🎯 Your Action Items for Day 13:

  1. ✅ Complete all 5 exercises
  2. ✅ Build the Library Management System
  3. ✅ Experiment with class vs instance attributes — break it intentionally
  4. ✅ Write a class that models something from your life (phone, pet, game character)

Comments

Popular posts from this blog

Day 1: Welcome to Python — Your Journey Begins

Python: Your Gateway to Coding Adventures

Day 11: List Comprehensions & Lambda Functions

Earn From the Comfort of Your Home

Build the skills to work comfortably from home, on your own terms.

Get Started Today