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

  1. Forgetting self — every method needs it as the first parameter, every attribute access uses self.
  2. Mutable class attributes — lists/dicts at the class level are shared between all instances; use __init__ instead
  3. 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.