Class Variables, Class Methods & Static Methods
Not all variables and methods belong to individual object instances. Sometimes you need data and actions that belong to the entire Class as a whole (such as counting total students enrolled in a university).
In this lesson, we will master Class Variables, Class Methods (@classmethod), and Static Methods (@staticmethod).
1. Learning Objective
By the end of this lesson, you will understand:
- What a Class Variable is and how it differs in RAM from an Instance Variable.
- How Class Methods (
@classmethod) operate on the class template usingcls. - What Static Methods (
@staticmethod) are and why they don't receiveselforcls. - When to use each of the three method types in real software architecture.
2. Why This Concept Exists
Imagine a university with 5,000 students:
- Every student has a unique
nameandage(Instance Variables). - But all 5,000 students share the exact same
university_nameandtotal_student_count.
If you stored university_name = "Osmania University" inside all 5,000 instance objects separately, you would waste RAM. More dangerously, if the university changed its name, you would have to update 5,000 separate memory boxes!
Class Variables store shared data in a single central Class Memory box. Class Methods manage this shared class data, while Static Methods provide standalone utility helper logic.
3. Common Beginner Confusions
Confusion 1: "What happens if I write s1.university_name = 'JNTU'?"
- Answer: DANGER! Writing
s1.university_name = 'JNTU'does NOT modify the shared Class Variable! Instead, Python creates a new instance variable nameduniversity_nameinsides1that shadows the class variable. To update the actual class variable, you MUST writeStudent.university_name = 'JNTU'.
Confusion 2: "When should I use @staticmethod instead of @classmethod or an instance method?"
- Answer:
- Use Instance Method (
self) if you need to read/modify instance attributes. - Use Class Method (
cls) if you need to read/modify class attributes or build alternative constructors. - Use Static Method if the function does not need to access instance data OR class data (e.g., validating an email address or converting Celsius to Fahrenheit).
- Use Instance Method (
4. Mental Model: School Notice Board vs. Student Notebook
-
School Notice Board (Class Variable):
- Placed in the central hallway (
StudentClass Memory). There is only one notice board. If the principal updates the exam date on the notice board, all students see the update instantly.
- Placed in the central hallway (
-
Student Notebook (Instance Variable):
- Stored inside each student's personal backpack (
s1Heap Object). Student A's notebook notes are independent of Student B's notebook notes.
- Stored inside each student's personal backpack (
-
School Bell (Static Method):
- Ringing the bell doesn't depend on Student A's marks or the Notice Board text. It is a general utility action.
5. Internal Python Execution Flow
Let's trace how Python resolves Class Variables and Methods:
Code Executed: s1.university_name
↓ Lookup Chain:
1. Python opens Heap Object s1 (0x9000).
2. Python checks if 'university_name' exists in s1's local dictionary.
3. Not found in s1!
4. Python follows s1's class pointer up to Class Object 'Student'.
5. Python finds 'university_name' in Class Memory and returns "Osmania University".
6. Memory Visualization: Class Memory vs Instance Objects
RAM Layout: Shared Class Memory vs Separate Instance Objects
CENTRAL CLASS MEMORY (class Student)
university_name = "Osmania University"
total_students = 2
↑ SHARED BY ALL INSTANCES ↑
name = "Sai"
age = 21
name = "Ananya"
age = 20
7. Python Code Implementation
class Student:
# 1. Class Variable (Shared across ALL instances)
university_name = "Osmania University"
total_students = 0
def __init__(self, name, age):
# Instance Variables
self.name = name
self.age = age
# Increment shared class variable using Class Name
Student.total_students += 1
# 2. Instance Method (Operates on self)
def introduce(self):
print(f"Hi, I am {self.name} from {Student.university_name}.")
# 3. Class Method (Operates on cls)
@classmethod
def get_total_students(cls):
return f"Total Enrolled Students: {cls.total_students}"
# 4. Static Method (Standalone utility - no self or cls)
@staticmethod
def is_valid_age(age):
return 17 <= age <= 60
# --- Execution ---
s1 = Student("Sai", 21)
s2 = Student("Ananya", 20)
# Calling Class Method
print(Student.get_total_students())
# Calling Static Method
print("Is age 15 valid?", Student.is_valid_age(15))
print("Is age 21 valid?", Student.is_valid_age(21))
Output:
Total Enrolled Students: 2
Is age 15 valid? False
Is age 21 valid? True
8. Line-by-Line Execution Analysis
Line: Student.total_students += 1 inside __init__
- What Python does: Python looks up Class Memory box
Student, fetchestotal_students(e.g.,0), increments it to1, and updates Class Memory. - Why not
self.total_students += 1? If you wroteself.total_students += 1, Python would create a local instance variables1.total_students = 1without incrementing the global class counter!
Line: @classmethod def get_total_students(cls):
- Decorator
@classmethod: Tells Python to pass the Class Object template itself intoclsinstead of an instance reference. - Access:
cls.total_studentsaccesses the central class memory variable directly.
Line: @staticmethod def is_valid_age(age):
- Decorator
@staticmethod: Tells Python NOT to passselforcls. It behaves like a plain function neatly grouped inside the class namespace.
9. Method Comparison Summary Table
| Method Type | Decorator | First Argument | Access Scope | Primary Use Case |
|---|---|---|---|---|
| Instance Method | None | self | Instance attributes (self.x) + Class attributes | Operating on individual object data |
| Class Method | @classmethod | cls | Class attributes (cls.x) only | Managing class-wide state or alternative constructors |
| Static Method | @staticmethod | None | No access to self or cls | Utility functions (validations, math conversions) |
10. Illustration Prompt for Diagram Generation
Excalidraw Diagram Prompt: A hand-drawn architectural diagram showing 3 method types in Python. At the top center, draw a large blue box labeled "Class Memory (Student)" containing Class Variable "university_name = Osmania", a Class Method box "@classmethod get_total(cls)", and a Static Method box "@staticmethod is_valid_age(age)". Below, draw two smaller green boxes labeled "Instance s1" and "Instance s2" with arrows pointing up to "Class Memory". Draw 3 distinct call arrows:
- Red arrow from s1 calling "s1.introduce()" pointing to Instance Data + Class Data.
- Purple arrow calling "Student.get_total_students()" going straight to Class Memory (cls).
- Gray arrow calling "Student.is_valid_age(21)" executing standalone without touching memory pointers. White background, clean hand-drawn look.
Quick Summary
- Class Variables are defined directly inside a class body and shared by ALL instances in a single Class Memory location.
- Instance Variables (
self.x) are unique to each individual Heap object. - Class Methods (
@classmethod) receiveclsand manipulate shared class state. - Static Methods (
@staticmethod) are utility helper functions that operate without receivingselforcls.