Class Variables vs Instance Variables

What's shared by the class and what belongs to each object

Intermediate 9 min

In this lesson

In Python, an instance variable belongs to a single object, while a class variable is shared by every object of a class. This lesson draws the line between the two and shows the classic trap that catches almost everyone once.

Explain it like I’m 5

An instance variable is your own backpack — only you carry it. A class variable is the classroom shelf everyone can reach. Change your backpack and nobody else is affected; change the shelf and everyone sees it.

One per object vs shared by all

An instance variable is created on self inside __init__, so each object gets its own copy. A class variable is defined directly in the class body, outside any method, and is shared by every object and by the class itself. Use a class variable for something genuinely common, like a school name or a game title.

Example
class Student:
    school = "PyLI5 Academy"      # shared by every student

    def __init__(self, name):
        self.name = name             # unique to each student

a = Student("Ada")
b = Student("Bo")
print(a.name, "-", a.school)
print(b.name, "-", b.school)
Output
Ada - PyLI5 Academy
Bo - PyLI5 Academy
Each student has their own name but shares one school.

The mutable class-variable trap

The danger appears when a class variable is a mutable object like a list or dict. Because every object shares the one list, appending through one object changes it for all of them. Almost always, per-object data belongs on self in __init__ instead.

Example
class Cart:
    items = []          # BUG: one list shared by every cart

    def add(self, thing):
        self.items.append(thing)

a = Cart()
b = Cart()
a.add("apple")
print(b.items)          # b sees a's item!
Output
['apple']
A shared mutable class variable leaks data between objects.
Example
class Cart:
    def __init__(self):
        self.items = []     # each cart gets its OWN list

    def add(self, thing):
        self.items.append(thing)

a = Cart()
b = Cart()
a.add("apple")
print(b.items)
Output
[]
Creating the list in __init__ gives each object its own.

Common mistake: Using a mutable class variable for per-object data

Why it happens:

Writing items = [] in the class body looks like a neat default, but it makes one list shared by every object.

How to fix it:

Create per-object collections in __init__ with self.items = [] so each object gets its own.

Common mistake: Changing a class variable when you meant to change one object

Why it happens:

Assigning to self.school versus ClassName.school behaves differently, and the difference is easy to miss.

How to fix it:

To change the shared value for everyone, assign through the class (Student.school = ...). Assigning self.school = ... instead creates a new instance variable that shadows the shared one for just that object.

In the Student example, which value is shared by every object?

Why is items = [] at class level dangerous for per-user carts?

Where should data that differs per object be created?

Mini exercise (medium)

Create a Player class with a shared game_name class variable and a per-player score that starts at 0. Add an add_points(points) method that increases this player’s score. Make two players, give them different points, and confirm their scores are separate.

Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.

class Player:
    game_name = "Space Blasters"   # shared by all players

    def __init__(self, name):
        self.name = name
        # TODO: give each player their own score, starting at 0

    def add_points(self, points):
        # TODO: add points to this player's score
        pass

p1 = Player("Ada")
p2 = Player("Bo")
p1.add_points(10)
p2.add_points(3)
print(p1.name, p1.score, "in", p1.game_name)
print(p2.name, p2.score, "in", p2.game_name)

What to learn next

You learned the difference between instance variables (one per object, set on self) and class variables (shared by every object), and why a mutable class variable like items = [] leaks data between objects. You gave a Player class a shared game_name while keeping each player’s score separate.

Now that one class is solid, the next step is reusing one class to build another. Inheritance Without the Headache covers parent and child classes, overriding methods, and super() — plus when inheritance helps and when it hurts. When you’re ready, continue to the next lesson.