Let's store and display information about a book:
- Store the title, author, and year
- Print a formatted summary
This presentation is designed for desktop or projector displays.
← Back to curriculumPYTHON OOP — COURSE 1
Blueprints, instantiation, self & magic methods
← → to navigate
Where we are in the journey
Let's store and display information about a book:
title = "Clean Code" author = "Robert Martin" year = 2008 print(f"{title} by {author} ({year})")
Parallel lists quickly become unwieldy:
titles = ["Clean Code", "Refactoring", ...] authors = ["Robert Martin", "Martin Fowler", ...] years = [2008, 1999, ...] for i in range(len(titles)): print(f"{titles[i]} by {authors[i]}")
Adding features means more parallel structures:
pages = [464, 431, ...] ratings = [4.7, 4.5, ...] is_available = [True, False, ...] def display_book(title, author, year, pages, rating): print(f"{title} by {author}") print(f"{pages} pages, rated {rating}")
What if code could be this simple?
book1 = Book("Clean Code", "Robert Martin", 2008) book1.display_info()
Data and behavior — bundled together.
We could group data with dicts:
book = {
"title": "Clean Code",
"author": "Robert Martin",
"year": 2008
}
print(book["titel"]) # KeyError!
Section
Everything around us is an object
Look around you. Everything is an object with attributes (what it has) and actions (what it does).
Has: color, speed, fuel
Does: accelerate, brake, turn
Has: name, grade, courses
Does: study, take exam, enroll
Has: water level, beans
Does: brew, grind, dispense
Every object in the real world has properties and behaviors.
What the object has
→ variables
What the object does
→ methods (functions)
Now let's translate this into Python code.
Section
A class describes what something IS and what it CAN DO
The data each object will hold
self.title = title self.author = author self.year = year
The behavior each object can perform
def display_info(self): print(f"{self.title}")
class Book: def __init__(self, title, author, year): self.title = title self.author = author self.year = year def display_info(self): print(f"{self.title} by {self.author} ({self.year})")
class Smartphone: def __init__(self, brand, color, battery_pct): self.brand = brand self.color = color self.battery_pct = battery_pct def make_call(self, number): print(f"{self.brand} calling {number}...") def check_battery(self): print(f"Battery: {self.battery_pct}%")
class Bicycle: def __init__(self, brand, gear_count): self.brand = brand self.gear_count = gear_count self.current_gear = 1 def shift_up(self): if self.current_gear < self.gear_count: self.current_gear += 1 print(f"Shifted to gear {self.current_gear}") def shift_down(self): if self.current_gear > 1: self.current_gear -= 1 print(f"Shifted to gear {self.current_gear}")
Syntax:
object_name = ClassName(parameters)
Example:
book1 = Book("Clean Code", "Robert Martin", 2008) book2 = Book("Refactoring", "Martin Fowler", 1999)
object_name.method_name(params)
Asks the object to do something
object_name.attribute
Reads the object's data
phone = Smartphone("iPhone", "black", 85) phone.make_call("555-1234") # iPhone calling 555-1234... phone.check_battery() # Battery: 85% print(phone.brand) # iPhone print(phone.color) # black
Python allows direct access to attributes:
phone.battery_pct = -50 # No error!
This can lead to invalid states.
We'll learn how to protect attributes in the next lecture: Encapsulation & Access Control
Section
How objects refer to themselves
Think of self like a person talking about themselves.
When you say "my name is...", self is the "my".
class Person: def __init__(self, name, age): self.name = name self.age = age def introduce(self): print(f"Hi, I'm {self.name}, age {self.age}")
person1 = Person("Alice", 25) person2 = Person("Bob", 30) person1.introduce() # Hi, I'm Alice, age 25 person2.introduce() # Hi, I'm Bob, age 30
class Person: def __init__(self, name, age): self.name = name self.age = age def compare_age(self, other_person): if self.age > other_person.age: print(f"{self.name} is older than {other_person.name}") else: print(f"{self.name} is not older than {other_person.name}") alice = Person("Alice", 25) bob = Person("Bob", 30) alice.compare_age(bob) # Alice is not older than Bob
person1.introduce()
Person.introduce(person1)
Section
Magic methods with double underscores
They let you define how your objects behave with built-in operations.
The constructor — called automatically when you create an object.
self as first parameterclass Book: def __init__(self, title, author): self.title = title self.author = author book = Book("Clean Code", "Martin") # __init__ called automatically
Called by len(obj)
Returns length/size of object
Called by obj1 + obj2
Defines addition behavior
Called by print(obj)
String representation
class MusicPlaylist: def __init__(self, name): self.name = name self.tracks = [] def add_track(self, track): self.tracks.append(track) def __len__(self): return len(self.tracks) playlist = MusicPlaylist("Road Trip") playlist.add_track("Bohemian Rhapsody") playlist.add_track("Hotel California") print(len(playlist)) # 2
class MusicPlaylist: def __init__(self, name, tracks=None): self.name = name self.tracks = tracks or [] def __add__(self, other): combined_name = f"{self.name} + {other.name}" combined_tracks = self.tracks + other.tracks return MusicPlaylist(combined_name, combined_tracks) rock = MusicPlaylist("Rock", ["Stairway", "Smoke"]) pop = MusicPlaylist("Pop", ["Thriller"]) combined = rock + pop # MusicPlaylist("Rock + Pop", [...])
class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector( self.x + other.x, self.y + other.y )
v1 = Vector(3, 4) v2 = Vector(4, 6) v3 = v1 + v2 print(v3.x, v3.y) # 7 10
For end users
Called by print() and str()
Readable, friendly output
For developers
Called in REPL and repr()
Unambiguous, often recreatable
class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day def __str__(self): return f"{self.day}/{self.month}/{self.year}" def __repr__(self): return f"Date({self.year}, {self.month}, {self.day})" d = Date(2026, 3, 12) print(d) # 12/3/2026 (calls __str__) print(repr(d)) # Date(2026, 3, 12) (calls __repr__)
Check if an object is an instance of a specific class:
book = Book("Clean Code", "Martin") print(isinstance(book, Book)) # True print(isinstance(book, str)) # False
def process_data(item): if isinstance(item, Book): item.display_info() elif isinstance(item, str): print(item) else: print("Unknown type")
Section
Seven reasons to think in objects
Break your program into self-contained units.
Has its own data and logic. Can be developed and tested independently.
If the payment fails, check the Payment class — not the entire codebase.
Create once, use many times.
class Customer: def __init__(self, name, email): self.name = name self.email = email c1 = Customer("Alice", "alice@example.com") c2 = Customer("Bob", "bob@example.com") c3 = Customer("Charlie", "charlie@example.com")
One class, unlimited objects.
Change one class, all objects reflect the update.
def display_info(self): print(self.title)
def display_info(self): print(f"{self.title} ({self.year})")
Every Book object now shows the year — no other code changed.
Hide complexity, expose a simple interface.
car.start_engine() # Simple interface # Complex internals hidden
Protect data, controlled access.
account.balance = -1000 # Anyone can break it
account.withdraw(100) # Validated, controlled
We'll dive deep into this in Lecture 2.
Same method name, different behavior.
for shape in [circle, rectangle, triangle]: shape.area() # Each calculates differently
We'll explore this in Lecture 4.
Objects in code correspond to real entities.
name, email, orders
name, price, stock
items, total, status
Your code structure mirrors the problem domain.
What is a class?
A) An object
B) A blueprint for creating objects
C) A variable
D) A function
A class is a blueprint (template) that defines the attributes and methods objects of that type will have
What is instantiation?
A) Deleting an object
B) Creating a class
C) Creating an object from a class
D) Calling a method
Instantiation is the process of creating a concrete object from a class blueprint
What does the __len__ method do?
A) Returns string representation
B) Returns the length of the object
C) Adds two objects together
D) Initializes an object
__len__ is called by the built-in len() function and should return the length of the object
Which is correct syntax to create an object?
A) Book.create("title")
B) new Book("title")
C) Book("title")
D) create Book("title")
In Python, you create objects by calling the class name directly with parentheses — no new keyword needed
What does self refer to?
A) The class itself
B) The current instance of the class
C) The parent class
D) A global variable
self refers to the specific object instance that called the method — each object has its own self
What is the difference between __str__ and __repr__?
A) They are identical
B) __str__ is for users, __repr__ is for developers
C) __repr__ is for users, __str__ is for developers
D) __str__ returns int, __repr__ returns string
__str__ provides a human-readable representation, while __repr__ provides an unambiguous developer-oriented representation
What's next
Next up: Encapsulation & Access Control
Questions?
See you next lecture for Encapsulation & Access Control