What Classes Are and Why
Layer 2 begins. A dictionary describes data. A class describes a kind of thing โ data plus the behavior that belongs with it. This is why we are switching.
A blueprint for a kind of thing, and the things built from it.
1. Learning Objective
By the end of this session you will be able to:
- Explain the difference between a dictionary and a class conceptually
- Define an empty class and create an instance of it
- Explain what an instance is, versus the class itself
- Explain why grouping data with the behavior that operates on it reduces bugs
- Recognise that this session is concept-only โ no meaningful code is written yet
2. Pre-Coding Quiz
Answer these before reading the concept explanation or writing any code. It is fine to get these wrong โ that is the point. You need 4/5 to proceed to the lab.
Given country = {"name": "Kenya"} and class Country: pass then c = Country(), what is the core difference between country and c?
What does class Country: pass define?
pass is a no-op placeholder statement, used here because a class body cannot be syntactically empty. This defines a minimal, valid class with nothing in it yet.What is c in c = Country()?
() constructs a new instance โ a specific, individual object that belongs to that class. Country is the blueprint; c is one thing built from it.If you defined a second instance c2 = Country(), is c the same object as c2?
Why is bundling data and the functions that operate on it (inside a class) considered better than passing loose dictionaries to loose functions everywhere?
3. The Concept โ Why Classes Exist
Country is the blueprint. c is one specific instance built from that blueprint โ a second call would build a separate one.
What we have been doing so far
For seven sessions, a country has been a dictionary, and every operation on it โ formatting, filtering, validating โ has been a separate, standalone function that takes the dictionary as an argument. This works, but nothing stops any function anywhere from reading or writing the wrong key, or writing an invalid value.
country = {"name": "Kenya", "population": 54000000}
def set_population(country, value):
if value < 0:
raise ValueError("population must be positive")
country["population"] = value
# Nothing stops this โ the dict has no memory of the rule above
country["population"] = -100
A class bundles data and behavior together
A class is a blueprint for a kind of thing. It groups the data that thing needs (its attributes) with the operations that belong to it (its methods) into a single definition. We will build this up piece by piece over the next several sessions โ today, just the shell.
class Country:
pass # placeholder โ a class body cannot be empty
c = Country()
print(type(c)) # <class '__main__.Country'>
print(isinstance(c, Country)) # True
Class vs instance โ a critical distinction
The class is the definition, written once. An instance is a specific object built from that definition โ you can build as many as you need, and each one is independent, just like each call to a function produces an independent result.
c1 = Country()
c2 = Country()
print(c1 is c2) # False โ two separate instances, even though both are Country
What this unlocks
Right now Country is an empty shell โ it does nothing a dictionary couldn't already do. Over the next several sessions we will give it attributes (Session 13), methods (Session 14), a proper constructor (Session 15), and eventually a whole tree of related classes (Session 16) โ building toward a real Country Explorer application.
4. Lab
What you will build
A file called country_class.py.
Step-by-step instructions
Create the file and define an empty class
# country_class.py
class Country:
pass
Create two separate instances
c1 = Country()
c2 = Country()
print(c1)
print(c2)
Confirm both are instances of Country
print(isinstance(c1, Country)) # True
print(isinstance(c2, Country)) # True
Prove they are two distinct objects, not the same one
Before running: predict what c1 is c2 will print, and why.
print(c1 is c2) # False โ separate objects in memory
Write a short comment explaining what problem this will eventually solve
No code required here โ write a plain-English comment in the file summarising, in your own words, why a class beats a loose dict + loose functions. This is the most important step in the lab.
# TODO: In your own words โ why will bundling country data and
# country behavior into one class reduce bugs compared to
# passing a dict to a bunch of separate functions?
5. Expected Files Changed
| File | Action | Why |
|---|---|---|
country_class.py |
Created | An empty Country class and proof that instances are independent. |
docs/sessions/session-12/index.html |
Created | This session document. |
6. Commit Checkpoint
Once the lab is complete and you can explain every line, make this exact commit:
git add country_class.py docs/sessions/session-12/index.html
git commit -m "session-12: define an empty Country class and confirm instances are independent"
7. Code Review Checklist
Go through your code line by line and check each item:
8. Post-Coding Quiz
Same 5 questions. Take it again now that you have written and run the code. You need 4/5 to mark this session complete.
Given country = {"name": "Kenya"} and class Country: pass then c = Country(), what is the core difference between country and c?
What does class Country: pass define?
pass is a no-op placeholder statement, used here because a class body cannot be syntactically empty. This defines a minimal, valid class with nothing in it yet.What is c in c = Country()?
() constructs a new instance โ a specific, individual object that belongs to that class. Country is the blueprint; c is one thing built from it.If you defined a second instance c2 = Country(), is c the same object as c2?
Why is bundling data and the functions that operate on it (inside a class) considered better than passing loose dictionaries to loose functions everywhere?
9. Reflection Questions
Think through these after the post-quiz. No right answer โ they are for discussion.
- Before this session, every "operation" on a country was a standalone function taking a dict. Can you think of a bug you might have written in the labs so far that a class could have prevented?
- Why do you think Python requires
passfor an empty class body instead of allowing nothing at all? - What is the relationship between a class and the
type()of an instance built from it? - If two instances of the same class can hold completely different data, what does that tell you about what a class actually "is" versus what an instance "is"?
10. What Breaks If This Knowledge Is Missing?
- Confusing the class with an instance: If you don't internalize the class/instance distinction now, later sessions (attributes, methods, inheritance) will feel like memorized syntax instead of a coherent mental model โ and debugging "why does every instance share this value" bugs becomes very hard.
- Attribute sessions ahead: Session 13 immediately builds on this by giving Country actual data via __init__. Without today's "class = blueprint, instance = built thing" model, __init__ will look like arbitrary magic syntax instead of a logical next step.
11. What We Learned
Python concept mastered: The class vs instance distinction, and the motivation for bundling data with behavior instead of using loose dicts and functions.
Unlocks: You have a mental model for what a class is FOR. Every remaining Layer 2 session builds directly on top of this.
Next session: Session 13 โ Class Anatomy โ __init__ and Attributes. We give Country real data โ an __init__ method and instance attributes, so every instance can hold its own name, region, and population.