Key Takeaways: Object-Oriented Programming — Thinking in Objects
One-Sentence Summary
Object-oriented programming bundles data (attributes) and behavior (methods) into objects created from class blueprints, giving you a powerful way to model real-world concepts and manage complexity in growing programs.
The OOP Mental Model
| Concept | What It Is | Example |
|---|---|---|
| Class | Blueprint / template | class Student: |
| Object (Instance) | A specific thing created from the blueprint | alice = Student("Alice", "S001") |
| Attribute | Data the object knows | alice.name, alice.grades |
| Method | Behavior the object can perform | alice.add_grade("CS101", 92) |
self |
Reference to the current object inside a method | Always the first parameter |
__init__ |
Constructor — sets up a new object | Runs automatically on creation |
Instance vs. Class Attributes
| Type | Defined Where | Shared? | Good For |
|---|---|---|---|
| Instance attribute | Inside __init__ with self.x = ... |
No — each object gets its own | Names, scores, inventories |
| Class attribute | In the class body, outside any method | Yes — one copy for all instances | Constants, counters, configuration |
Rule: If it's mutable (list, dict, set), put it in __init__. Class-level mutable attributes are shared and cause bugs.
Essential Special Methods (Dunders)
| Method | Purpose | Called By |
|---|---|---|
__init__(self, ...) |
Initialize new objects | MyClass(...) |
__str__(self) |
Human-readable display | print(obj), str(obj) |
__repr__(self) |
Developer/debugging display | REPL, repr(obj), containers |
__eq__(self, other) |
Value equality | obj1 == obj2 |
__lt__(self, other) |
Less-than comparison | sorted(), < operator |
__len__(self) |
Length/size | len(obj) |
Encapsulation Conventions
| Convention | Meaning | Access |
|---|---|---|
self.name |
Public | Use freely from anywhere |
self._name |
Protected | Internal — use at your own risk |
self.__name |
Name-mangled | Strongly discouraged external access |
@property |
Controlled access | Looks like an attribute, works like a method |
When to Use OOP vs. Procedural
Use OOP when: - You're modeling "things" with identity, state, and behavior (nouns: Student, Task, Room) - Multiple related data items belong together - You need multiple instances of the same concept - State changes over time and needs tracking
Stay procedural when: - You're writing stateless utility functions (verbs: calculate, parse, convert) - You have a simple input-to-output transformation - No instances or shared state are needed
Most real programs use both. Classes for domain objects, functions for utilities.
Three Pitfalls to Avoid
- Forgetting
self— every method needs it as the first parameter, every attribute access usesself. - Mutable class attributes — lists/dicts at the class level are shared between all instances; use
__init__instead - God classes — split large classes into focused ones, each with a single responsibility
The Threshold Concept
Before: "I have data in variables and functions that operate on that data — separately."
After: "I have objects that KNOW things (attributes) and can DO things (methods)."
When you look at a problem and think "this thing has properties and actions," reach for a class.
TaskFlow v1.3 Architecture
| Class | Responsibility |
|---|---|
Task |
Represents a single task — title, priority, completion, serialization |
TaskList |
Manages a collection of tasks — add, delete, search, filter |
TaskStorage |
Handles persistence — save to and load from JSON |
What's Next
Chapter 15 introduces inheritance (building new classes on top of existing ones) and polymorphism (different objects responding to the same method in different ways). TaskFlow will gain DeadlineTask, RecurringTask, and ChecklistTask subclasses.