Learning Goals
3 minBy the end of this lesson you can:
- Explain why parallel lists go wrong, and what a class fixes.
- Define a class with
classand a docstring. - Create objects from it, and give each one its own attributes.
- Read
mia.scoreout loud and say exactly what it means.
Warm-Up · Three Lists, One Bug
5 minThe coding club keeps its records in three lists. Read this, and predict the last line before you run it.
names = ["Mia", "Leo", "Ana"] scores = [78, 91, 65] lives = [3, 2, 3] # Leo leaves the club names.pop(1) scores.pop(1) print(names[1], scores[1], lives[1])
Answer
Output
Ana 65 2
Ana's name and score are right. Her lives are Leo's, because lives never had anything removed. Nothing crashed, nothing warned you — the program simply started telling lies.
Mia is not a name, a score and a number of lives. She is one pupil whose data got scattered across three lists that must be kept in step by hand. Every list you add is one more chance to forget. A class puts her back together.
New Concept · A Blueprint and the Things You Stamp Out
12 minThink of a biscuit cutter. The cutter is not a biscuit. It is the shape of a biscuit, and you use it to make dozens of them.
- A class is the cutter — one description of a kind of thing.
- An object is a biscuit — a real thing made from that description.
You write the class once. You make objects from it as often as you like.
1 · The class — a name, a colon, and an indented body. Nothing exists yet except the description.
class Student: """One pupil in the coding club."""
Three things to notice:
class— the keyword, just asdefstarts a function.Student— PascalCase: capital letter, no underscores. That capital is how every Python reader spots a class at a glance.- The docstring is the whole body for now. If you prefer, write
passinstead — a class needs something indented under it.
2 · The objects — brackets after the name make a new one, exactly like calling a function.
mia = Student() ana = Student()
That is two separate students. They came from the same blueprint, but they are not the same thing.
3 · The attributes — a piece of data stored on one object. The dot means "belonging to".
mia.name = "Mia" mia.score = 78 ana.name = "Ana" ana.score = 65 print(mia.score) print(ana.score)
Output
78 65
Read mia.score as "the score belonging to mia". Each object has its own, and changing one never touches the other.
Student is the class. mia is a variable holding one object. Classes get PascalCase, variables stay snake_case — so Student() is obviously a blueprint being used, and mia is obviously one pupil.
Python will tell you what an object is if you ask it:
print(type(mia))
Output
<class '__main__.Student'>
Nothing in that class says a student has a name and a score. You attach them by hand afterwards, and Python is happy either way. Miss one and you get AttributeError later; mistype mia.scor = 80 and Python quietly creates a brand-new attribute. Next lesson gives every object its data at the moment it is born.
Worked Example · The Club List, Rewritten
12 minType this out and run it. It holds the same information as the three lists in the warm-up.
class Student: """One pupil in the coding club.""" mia = Student() mia.name = "Mia" mia.score = 78 mia.lives = 3 wei_jie = Student() wei_jie.name = "Leo" wei_jie.score = 91 wei_jie.lives = 2 ana = Student() ana.name = "Ana" ana.score = 65 ana.lives = 3 print(mia.name, "scored", mia.score) print(wei_jie.name, "scored", wei_jie.score) print(ana.name, "scored", ana.score) # Leo leaves the club - one line, and all of his data goes with him del wei_jie print("Ana still has", ana.lives, "lives")
Output
Mia scored 78 Leo scored 91 Ana scored 65 Ana still has 3 lives
Now try the thing that broke the warm-up. Delete a pupil and check the others. Nothing shifts, nothing goes out of step, because nobody's data was ever stored by position.
Before: three lists, and the truth about Ana was "whatever is at index 2 of all three". After: one object, and the truth about Ana is "whatever is written on ana". Removing her is one line. Adding a fourth fact about her — a form class, a favourite language — is one line too, and no other student is affected.
Add a new pupil to prove it:
hugo = Student() hugo.name = "Hugo" hugo.score = 84 hugo.lives = 3 print(hugo.name, "joined with", hugo.lives, "lives")
Output
Hugo joined with 3 lives
Try It Yourself
13 minWrite a class called Drink. Make three objects — cocoa, kopi_o and cocoa_ais — and give each one a name and a price. Print one tidy line per drink.
Hint
class Drink: """One drink on the stall menu.""" cocoa = Drink() cocoa.name = "Hot chocolate" cocoa.price = 2.50 print(cocoa.name, "costs $", cocoa.price)
Write a class called Stall with three attributes on each object: owner, food and price. Make two stalls and print a line for each.
Then do two experiments:
- Change one stall's price and print both again. Confirm the other stall did not move.
- Add a fourth attribute —
stall.halal = True— to one stall only, then try to print it on the other. Read the error message carefully; it is the exact problem lesson 2 solves.
Mini-Challenge 🔥 · Debug: Three Ways to Break a Class
8 minFelix's game crashes on the last line, and one earlier line is doing something he did not intend. There are three problems. Find them all before you look.
class player:
"""One player in the game."""
hero = player
hero.name = "Felix"
hero.hp = 100
print(hero.name, "has", hero.hp, "HP")
print("Lives left:", hero.lives)Answer
- The class name is lower case.
class playerruns, but every Python reader expectsPlayer. PascalCase is how you tell a blueprint from a variable at a glance. - No brackets.
hero = playergives the blueprint a second name — it does not stamp out an object. Every attribute then lands on the class itself, so a second player would share Felix's name and HP. It must behero = Player(). hero.liveswas never set. Python only knows the attributes you assign, so reading it raisesAttributeError: 'Player' object has no attribute 'lives'.
There is a quieter problem underneath all three: nothing in the class says a player has a name, HP and lives. That is not something you can fix by being careful — it needs __init__, which is the whole of lesson 2.
Recap
3 minA class is a blueprint for a kind of thing; an object is one thing made from it. class Student: describes, Student() creates, and mia.score = 78 writes a piece of data onto one object. The dot means "belonging to". Classes are PascalCase, objects are ordinary snake_case variables. The win is that one thing's data now lives in one place instead of being spread across parallel lists that can drift apart.
Vocabulary Card
- class
- A blueprint describing a kind of thing. Written once, in PascalCase.
- object
- One real thing made from a class. Also called an instance.
- instantiate
- To make an object from a class, by writing the class name with brackets.
- attribute
- A piece of data stored on one object, reached with a dot:
ana.score.
Homework
4 minPick something real from your own life and model it as a class — a book on your shelf, a bus on your route home, a cat in your neighbourhood.
- Write the class, with a docstring saying what one of them is.
- Make three objects, each with at least three attributes.
- Print one tidy line per object.
- Add one sentence: how many lists would you have needed without a class?
Hint: choose a noun, then list the words that follow "its" — its title, its author, its price. Those are your attributes.
Sample · rak_buku.py
# rak_buku.py - three books on one shelf class Book: """One book on my shelf.""" sejarah = Book() sejarah.title = "Sejarah Tingkatan 2" sejarah.author = "Kementerian Pendidikan" sejarah.price = 12.90 komik = Book() komik.title = "Lat: Village Boy" komik.author = "Lat" komik.price = 24.00 python_book = Book() python_book.title = "Python for Kids" python_book.author = "Jason Briggs" python_book.price = 79.90 shelf = [sejarah, komik, python_book] for book in shelf: print(book.title, "by", book.author, "- $", book.price)
Without a class this needs three parallel lists, kept in step by hand. The final loop peeks ahead at lesson 4 — a list of objects — but three separate print lines is a perfectly good answer for today.