Learning

Instance vs Class Variables

Instance vs Class Variables

The Core Difference

python
class Dog: # Class variable: shared by ALL dogs species = 'Canis familiaris' def __init__(self, name): # Instance variable: unique to EACH dog self.name = name dog1 = Dog('Rex') dog2 = Dog('Buddy') # Instance variables are independent dog1.name = 'Max' print(dog1.name) # 'Max' print(dog2.name) # 'Buddy' (unchanged) # Class variable is shared print(dog1.species) # 'Canis familiaris' print(dog2.species) # 'Canis familiaris'

Attribute Resolution Order

python
# 1. Instance __dict__ # 2. Class __dict__ # 3. Parent class __dict__ (if inherited) class Test: x = 'Class Level' def __init__(self): self.x = 'Instance Level' t = Test() print(t.x) # 'Instance Level' (found here first!) print(Test.x) # 'Class Level' del t.x # Delete instance variable print(t.x) # 'Class Level' (falls back to class!)

⚠️ The Mutable Class Variable Trap

python
# Mutable class variable (LIST) items = [] def __init__(self, name): self.name = name a = Bad('A') b = Bad('B') a.items.append('apple') # Modifies the SHARED list! print(b.items) # ['apple'] 🐛 Bug!

Fix: Initialize mutable objects inside __init__

python
class Good: def __init__(self, name): self.name = name self.items = [] # Fresh list for EACH instance a = Good('A') b = Good('B') a.items.append('apple') print(b.items) # [] (Safe!)

When to Use Class Variables

python
class Circle: PI = 3.14159 # 2. Counters class User: user_count = 0 def __init__(self, name): self.name = name User.user_count += 1 # 3. Caching/Shared state class Config: _settings = {} @classmethod def set(cls, key, val): cls._settings[key] = val

Accessing Class Variables

python
class MyClass: count = 0 def __init__(self): # ⚠️ Ambiguous: creates INSTANCE variable if assigned! # self.count = 1 def increment_bad(self): self.count += 1 # Creates INSTANCE var, shadows CLASS var! def increment_good(self): MyClass.count += 1 # ✅ Correctly modifies CLASS var @classmethod def increment_cls(cls): cls.count += 1 # ✅ Also correct, more flexible
Key Rules
  • •Instance variables (self.x) are unique to each object; class variables (Class.x) are shared across all instances
  • •NEVER use mutable objects (lists, dicts) as class variables — they are shared and cause cross-instance contamination
  • •Always initialize mutable instance attributes inside __init__, not at the class level
  • •Inside methods, use ClassName.var or cls.var to modify class variables — self.var += 1 creates an instance variable!
  • •Python looks up attributes in order: instance dict → class dict → parent class dict
Your Task

Create a `Circle` class with a class variable `PI = 3.14159` and an instance variable `radius`. Add methods `area()` and `circumference()` using `Circle.PI`. Then create a `BugDemo` class with a class variable `shared_list = []`. Show the bug: create two instances, append to one's list, and print the other's list. Then fix it by moving the list initialization to `__init__` in `FixedDemo`.

EditorPython · JSX
PreviewUpdates on Run Tests
Loading preview…
Tests
Should define Circle class with class variable PI
Should use Circle.PI in methods
Should define BugDemo with shared_list = []
Should define FixedDemo with __init__
FixedDemo should initialize list in __init__
Should demonstrate bug2 accessing shared_list