📘 Lesson 19 · Intermediate

Python OOP — Object-Oriented Programming

Learn classes, objects, __init__, methods, self, and dunder methods with clear examples.

What is OOP?

Object-Oriented Programming organises code around objects — bundles that group related data and functions together. A class is the blueprint; an instance (object) is a specific copy built from it. For example, a Dog class defines what every dog has (name, age) and can do (bark). Each real dog — Rex, Bella — is an object with its own specific values. OOP makes large programs easier to manage by hiding internal details and enabling code reuse through inheritance.

Defining a Class

The __init__ method (the constructor) runs automatically when a new object is created and sets up its initial state. self refers to the current instance and must be the first parameter of every instance method — though Python passes it automatically; you never supply it manually when calling.

dog.py
class Dog:
    species = "Canis familiaris"  # class var — shared by all dogs

    def __init__(self, name, age):
        self.name = name   # instance var — unique per dog
        self.age = age

    def bark(self):
        print(f"{self.name}: Woof!")

    def birthday(self):
        self.age += 1
        print(f"{self.name} is now {self.age}")

rex = Dog("Rex", 3)
bella = Dog("Bella", 5)
rex.bark()
bella.birthday()
▶ Output
Rex: Woof!
Bella is now 6

Each object has its own copy of instance variables (self.name, self.age), but all objects share class variables. Changing Dog.species changes it for every dog instance.

The __str__ Dunder Method

By default, printing an object shows an unhelpful memory address like <Dog object at 0x...>. Define __str__ to control what print(obj) displays. These special double-underscore methods (called dunder methods) let objects work naturally with Python's built-in operations.

book.py
class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):
        return f'"{self.title}" by {self.author} ({self.pages}p)'

    def __len__(self):
        return self.pages

b = Book("Python Crash Course", "Matthes", 544)
print(b)
print(f"Pages: {len(b)}")
▶ Output
"Python Crash Course" by Matthes (544p)
Pages: 544
Define __str__ for human-readable output and __repr__ for developer/debugging output. Both are useful in different contexts.

🧠 Quick Check

What is the first parameter of every instance method?

this
cls
self
me

Tags

OOPclassobject__init__selfmethodsdunder__str__