Table of Contents
- What Are Class and Instance Variables?
- Class Variables: Shared Among All Instances
- 2.1 Definition and Declaration
- 2.2 Accessing Class Variables
- 2.3 Modifying Class Variables
- 2.4 Examples of Class Variables
- Instance Variables: Unique to Each Instance
- 3.1 Definition and Declaration
- 3.2 Accessing Instance Variables
- 3.3 Modifying Instance Variables
- 3.4 Examples of Instance Variables
- Key Differences Between Class and Instance Variables
- Common Pitfalls and How to Avoid Them
- 5.1 Accidentally Modifying Class Variables via Instances
- 5.2 Mutable Class Variables and Shared State
- Practical Use Cases
- 6.1 When to Use Class Variables
- 6.2 When to Use Instance Variables
- Advanced Scenarios: Class and Instance Variable Interactions
- 7.1 Overriding Class Variables in Subclasses
- 7.2 Shadowing Class Variables with Instance Variables
- Conclusion
- References
1. What Are Class and Instance Variables?
In Python, variables defined within a class fall into two main categories:
- Class Variables: Belong to the class itself, not individual instances. They are shared across all instances of the class.
- Instance Variables: Belong to a specific instance (object) of the class. Each instance has its own copy, so values are unique to that object.
Think of a class as a blueprint for a house. A class variable would be a feature shared by all houses built from the blueprint (e.g., “number of walls = 4”), while an instance variable would be unique to a specific house (e.g., “paint color = blue” for one house, “paint color = red” for another).
2. Class Variables: Shared Among All Instances
2.1 Definition and Declaration
A class variable is a variable declared inside the class but outside any instance methods (like __init__). It is owned by the class, not by individual instances, so all instances of the class share the same value for the class variable.
Declaration Syntax:
class ClassName:
class_variable = value # Declared here, outside methods
def __init__(self):
# Instance variables declared here (see Section 3)
2.2 Accessing Class Variables
Class variables can be accessed in two ways:
- Directly via the class name:
ClassName.class_variable. - Via an instance of the class:
instance.class_variable(though this is less common and can lead to confusion).
Example:
class Car:
wheels = 4 # Class variable: all cars have 4 wheels
# Access via class name
print(Car.wheels) # Output: 4
# Access via instance
my_car = Car()
print(my_car.wheels) # Output: 4 (shares the class variable)
2.3 Modifying Class Variables
To modify a class variable and have the change affect all instances, you must modify it via the class itself (not an instance). Modifying it via an instance creates a shadow instance variable (see Pitfall 5.1), which overrides the class variable for that specific instance but leaves the class variable unchanged.
Example: Modifying via Class (Correct)
class Car:
wheels = 4
# Modify via class
Car.wheels = 6 # All cars now have 6 wheels (hypothetically)
my_car = Car()
your_car = Car()
print(my_car.wheels) # Output: 6 (change affects all instances)
print(your_car.wheels) # Output: 6
Example: Modifying via Instance (Avoid!)
class Car:
wheels = 4
my_car = Car()
my_car.wheels = 3 # Creates a shadow instance variable for my_car
print(my_car.wheels) # Output: 3 (instance variable overrides class variable)
print(Car.wheels) # Output: 4 (class variable remains unchanged)
print(your_car.wheels) # Output: 4 (other instances use the class variable)
2.4 Examples of Class Variables
Example 1: Tracking Instance Count
Class variables are useful for counting how many instances of a class have been created:
class Student:
total_students = 0 # Class variable to track count
def __init__(self, name):
self.name = name # Instance variable (see Section 3)
Student.total_students += 1 # Increment class variable on initialization
# Create instances
alice = Student("Alice")
bob = Student("Bob")
print(Student.total_students) # Output: 2 (two instances created)
Example 2: Storing Constants
Class variables can act as constants shared across all instances:
class MathConstants:
PI = 3.14159
E = 2.71828
print(MathConstants.PI) # Output: 3.14159
print(MathConstants.E) # Output: 2.71828
3. Instance Variables: Unique to Each Instance
3.1 Definition and Declaration
Instance variables are variables unique to each instance of a class. They are declared inside instance methods (most commonly the __init__ constructor) using the self keyword, which refers to the current instance.
Declaration Syntax:
class ClassName:
def __init__(self, param1, param2):
self.instance_variable1 = param1 # Instance variable
self.instance_variable2 = param2 # Instance variable
3.2 Accessing Instance Variables
Instance variables are accessed via the instance (using self inside methods or the instance name outside the class). They cannot be accessed directly via the class name (unlike class variables).
Example:
class Person:
def __init__(self, name, age):
self.name = name # Instance variable
self.age = age # Instance variable
# Create an instance
person = Person("Alice", 30)
# Access via instance
print(person.name) # Output: Alice
print(person.age) # Output: 30
# Access via self inside a method
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, I'm {self.name} and I'm {self.age} years old."
person = Person("Bob", 25)
print(person.greet()) # Output: Hello, I'm Bob and I'm 25 years old.
3.3 Modifying Instance Variables
Modifying an instance variable affects only the specific instance it belongs to. This is done via the instance (or self inside methods).
Example:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
alice = Person("Alice", 30)
bob = Person("Bob", 25)
# Modify Alice's age
alice.age = 31
print(alice.age) # Output: 31 (only Alice's age changes)
print(bob.age) # Output: 25 (Bob's age remains unchanged)
3.4 Examples of Instance Variables
Example: Object-Specific Attributes
Instance variables store data unique to each object, such as a user’s email or a car’s VIN:
class User:
def __init__(self, username, email):
self.username = username # Unique to each user
self.email = email # Unique to each user
user1 = User("alice123", "[email protected]")
user2 = User("bob456", "[email protected]")
print(user1.email) # Output: [email protected]
print(user2.email) # Output: [email protected] (different from user1)
4. Key Differences Between Class and Instance Variables
| Feature | Class Variables | Instance Variables |
|---|---|---|
| Ownership | Belong to the class. | Belong to individual instances. |
| Memory | Stored once in memory (shared across all instances). | Stored separately for each instance. |
| Access | Accessible via the class or any instance. | Accessible only via the instance (or self). |
| Modification Impact | Modifying via the class affects all instances. | Modifying affects only the specific instance. |
| Typical Use Case | Shared constants, counters, or default values. | Object-specific attributes (e.g., name, age). |
5. Common Pitfalls and How to Avoid Them
5.1 Accidentally Modifying Class Variables via Instances
As shown in Section 2.3, modifying a class variable via an instance creates a shadow instance variable, which hides the class variable for that instance but leaves the class variable unchanged. This can lead to subtle bugs.
Example of the Pitfall:
class Counter:
count = 0 # Class variable
# Create instances
c1 = Counter()
c2 = Counter()
# Accidentally modify via instance (instead of class)
c1.count = 1 # Creates shadow instance variable for c1
print(c1.count) # Output: 1 (shadow variable)
print(c2.count) # Output: 0 (class variable unchanged)
print(Counter.count) # Output: 0 (class variable unchanged)
Fix: Always modify class variables via the class itself (Counter.count += 1), not instances.
5.2 Mutable Class Variables and Shared State
If a class variable is a mutable object (e.g., a list, dictionary), modifying it via an instance will affect all instances, even if you use self or the instance name. This is because mutable objects are passed by reference, so all instances share the same underlying object.
Example of the Pitfall:
class Warehouse:
products = [] # Mutable class variable (list)
w1 = Warehouse()
w2 = Warehouse()
# Add a product via w1 (modifies the shared list)
w1.products.append("Laptop")
print(w1.products) # Output: ['Laptop']
print(w2.products) # Output: ['Laptop'] (w2 sees the change too!)
print(Warehouse.products) # Output: ['Laptop'] (class variable modified)
Fix: Avoid mutable class variables unless intentional. If you need per-instance mutable data, use instance variables:
class Warehouse:
def __init__(self):
self.products = [] # Instance variable (unique per warehouse)
w1 = Warehouse()
w2 = Warehouse()
w1.products.append("Laptop")
print(w1.products) # Output: ['Laptop']
print(w2.products) # Output: [] (no shared state)
6. Practical Use Cases
6.1 When to Use Class Variables
- Constants: Values that don’t change (e.g.,
MathConstants.PI). - Counters: Tracking the number of instances created (e.g.,
Student.total_students). - Shared Defaults: Values shared across all instances (e.g.,
Car.wheels = 4). - Configuration: Shared settings for all instances (e.g.,
APIClient.timeout = 10).
6.2 When to Use Instance Variables
- Object-Specific Data: Attributes unique to each instance (e.g.,
Person.name,User.email). - Stateful Data: Data that changes per instance (e.g.,
BankAccount.balance). - Mutable Data per Instance: When each instance needs its own copy of a mutable object (e.g.,
ShoppingCart.items).
7. Advanced Scenarios: Class and Instance Variable Interactions
7.1 Overriding Class Variables in Subclasses
Subclasses can override parent class variables by redefining them. This allows subclasses to have their own version of the class variable while inheriting other behavior.
Example:
class Animal:
sound = "Generic sound" # Parent class variable
class Dog(Animal):
sound = "Bark" # Override parent class variable
class Cat(Animal):
sound = "Meow" # Override parent class variable
dog = Dog()
cat = Cat()
print(dog.sound) # Output: Bark
print(cat.sound) # Output: Meow
7.2 Shadowing Class Variables with Instance Variables
If an instance variable has the same name as a class variable, the instance variable “shadows” (takes precedence over) the class variable for that instance.
Example:
class MyClass:
x = 10 # Class variable
obj = MyClass()
obj.x = 20 # Instance variable with same name (shadows class variable)
print(obj.x) # Output: 20 (instance variable)
print(MyClass.x) # Output: 10 (class variable unchanged)
8. Conclusion
Class and instance variables are foundational to Python OOP, enabling you to model shared and object-specific data. To recap:
- Class variables belong to the class and are shared across all instances. Modify them via the class to affect all instances.
- Instance variables belong to individual instances and store unique data. Modify them via instances to affect only that object.
- Avoid pitfalls like modifying class variables via instances or using mutable class variables for per-instance data.
By mastering these concepts, you’ll write more predictable, efficient, and maintainable Python code.
9. References
- Python Official Documentation: Classes
- Real Python: Class and Instance Variables
- Fluent Python by Luciano Ramalho (Chapter 9: Classes and Objects)