Lesson 161 of 1596
Python Classes & OOP — Modeling Your World in Code
Classes let you bundle data with the behavior that operates on it. You'll build a class for a real thing and use AI to refactor it with confidence.
Creators · AI-Assisted Coding · ~30 min read
When functions aren't enough
A function takes inputs and returns outputs. A class groups related functions with the data they share, so you stop passing the same five arguments to every call. In 2026 Python, @dataclass makes writing classes almost free.
@dataclass auto-generates __init__, __repr__, and __eq__. No boilerplate.
from dataclasses import dataclass, field from datetime import datetime @dataclass class Task: title: str priority: int = 3 done: bool = False created_at: datetime = field(default_factory=datetime.now) def complete(self) -> None: self.done = True def age_seconds(self) -> float: return (datetime.now() - self.created_at).total_seconds() t = Task("Write essay", priority=1) t.complete() print(t) # Task(title='Write essay', priority=1, done=True, )self, methods, and instance data
- self is the first parameter of every instance method — Python passes the instance in automatically
- Methods are just functions that live inside a class
- Instance attributes are scoped to one object; class attributes are shared
Inheritance — build on what exists
RecurringTask gets everything Task has, plus new fields and methods.
@dataclass class RecurringTask(Task): interval_days: int = 7 def next_due(self) -> datetime: from datetime import timedelta return self.created_at + timedelta(days=self.interval_days) r = RecurringTask("Water plants", interval_days=3) print(r.next_due()) r.complete() # inherited from TaskError handling with typed exceptions
Custom exceptions let callers handle specific failures without parsing error strings.
class TaskError(Exception): """Base class for task errors.""" class TaskAlreadyDoneError(TaskError): pass @dataclass class SafeTask(Task): def complete(self) -> None: if self.done: raise TaskAlreadyDoneError(f"{self.title!r} is already done") self.done = True try: t = SafeTask("Study") t.complete() t.complete() # second call raises except TaskAlreadyDoneError as e: print(f"Caught: {e}")Mini-exercise
- 1Design a BankAccount @dataclass with owner, balance, and transactions (list)
- 2Add methods deposit(amount) and withdraw(amount)
- 3withdraw should raise InsufficientFundsError if balance < amount
- 4Have your AI assistant write unit tests for the happy and failure paths
Compare the options
| Plain function | Class |
|---|---|
| Stateless | Holds state |
| Easy to test | Still easy with dataclass |
| Good for: one-shot logic | Good for: long-lived things (users, accounts, sessions) |
| No setup cost | A little boilerplate, a lot of clarity |
Big idea: classes model the nouns of your program. When you find yourself passing the same blob of data everywhere, it wants to be a class.
End-of-lesson quiz
Check what stuck
8 questions · Score saves to your progress.
Tutor
Curious about “Python Classes & OOP — Modeling Your World in Code”?
Ask anything about this lesson. I’ll answer using just what you’re reading — short, friendly, grounded.
Progress saved locally in this browser. Sign in to sync across devices.
Related lessons
Keep going
Creators · 45 min
Python Classes and OOP With AI
Classes group state and behavior. Dataclasses cut boilerplate. Let AI scaffold while you understand what's under the hood.
Creators · 50 min
Installing and Using Claude Code CLI
Claude Code is Anthropic's terminal-native coding agent. Let's install it, wire it to a project, and use the features most engineers miss on day one.
Creators · 45 min
Installing and Using the OpenAI Codex CLI
Codex CLI is OpenAI's terminal coding agent. It runs locally, supports MCP, and ships a codex cloud mode for background tasks. Let's install it and compare it honestly to Claude Code.
