Class vs instance attributes
Overview
Class variables are shared across all instances of a class, whereas instance variables are unique to each specific object. Think of a class variable as a shared whiteboard in a conference room, while instance variables are each employee's personal notebook. When Python looks up an attribute (e.g., `self.name`), it checks the instance's dictionary first; if not found, it falls back to the shared class dictionary.
It allows you to store state that applies to the entire group (like a connection pool, a constant, or a shared counter) without duplicating it in every object, saving memory and keeping state centralized.
Where used: Django Model fields, SQLAlchemy declarative base, Pydantic schema definitions
Why learn this
- Django ORM models use class variables to define database columns
- Pydantic models use class variables with type hints for schema definition
- Avoiding accidental shared state bugs across instances
Code walkthrough
class Employee:
company = 'Acme Corp'
def __init__(self, name):
self.name = name
e1 = Employee('Alice')
e2 = Employee('Bob')
print(e1.company)
print(e2.company)
Employee.company = 'GlobalTech'
print(e1.company)
Focus: Employee.company = 'GlobalTech' changes the class variable, affecting the output of e1.company since e1 falls back to the class.
Aha moment
class Server:
logs = []
def __init__(self, name):
self.name = name
s1 = Server('web')
s2 = Server('db')
s1.logs.append('started')
print(s2.logs)
Prediction: What does this print?
Common guess: []
Because `logs` is a class variable, `s1.logs.append()` mutates the single shared list. To give each server its own logs, `logs = []` must be assigned to `self` in `__init__`.
Common mistakes
- Mutating shared class variables: Modifying a mutable class variable (like a list or dict) through an instance changes it for all instances because they all point to the exact same object in memory. Fix: Initialize mutable variables inside `__init__` as instance variables.
- Shadowing class variables: Assigning to an attribute via `self.var = value` creates an instance variable, hiding the class variable of the same name for that specific instance, rather than updating the shared class variable.
Glossary
- connection pool
- A cache of active database connections that can be reused, saving the time and effort of creating a new connection every time. Example: `engine = create_engine(url, pool_size=5)` creates a pool of 5 reusable connections.
- schema definition
- A structured plan or blueprint that describes how data should be organized and what types of data are allowed. Example: `class User(BaseModel): name: str; age: int` is a schema definition in Pydantic.
Recall questions
- Where does Python look first when you try to read an attribute from an object?
- What is the difference in how instance and class variables are shared?
Understanding checks
What will this code print?
['roll over']
Because ricks is a class variable and a mutable list, it is shared across all instances. Modifying it via one instance affects the shared list seen by all other instances.
If you have a class variable counter = 0 and you execute self.counter = 5 inside an instance method, what happens?
It creates a new instance variable named counter for that specific instance, shadowing the class variable. The class variable remains 0.
Assigning directly to self.attribute always writes to the instance's dictionary. It does not update the shared class dictionary unless you explicitly use the class name, like MyClass.counter = 5.
Practice tasks
Fix the connection counter
The provided Connection class tracks connections incorrectly by updating an instance variable instead of the class variable. Modify the __init__ method so it properly increments the shared otal_connections class variable.
Challenge
Fix the Shared Cache Bug
The `Route` class below uses a class variable to store cached responses. Unfortunately, every route is sharing the exact same cache dictionary! Fix it by moving the cache to be an instance variable so each route has its own empty dictionary when created.