Skip to main content

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 using cls.
  • What Static Methods (@staticmethod) are and why they don't receive self or cls.
  • 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 name and age (Instance Variables).
  • But all 5,000 students share the exact same university_name and total_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 named university_name inside s1 that shadows the class variable. To update the actual class variable, you MUST write Student.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).

4. Mental Model: School Notice Board vs. Student Notebook

  1. School Notice Board (Class Variable):

    • Placed in the central hallway (Student Class Memory). There is only one notice board. If the principal updates the exam date on the notice board, all students see the update instantly.
  2. Student Notebook (Instance Variable):

    • Stored inside each student's personal backpack (s1 Heap Object). Student A's notebook notes are independent of Student B's notebook notes.
  3. 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 ↑

Instance s1 (0x9000)

name = "Sai"
age = 21

Instance s2 (0x9100)

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, fetches total_students (e.g., 0), increments it to 1, and updates Class Memory.
  • Why not self.total_students += 1? If you wrote self.total_students += 1, Python would create a local instance variable s1.total_students = 1 without incrementing the global class counter!

Line: @classmethod def get_total_students(cls):

  • Decorator @classmethod: Tells Python to pass the Class Object template itself into cls instead of an instance reference.
  • Access: cls.total_students accesses the central class memory variable directly.

Line: @staticmethod def is_valid_age(age):

  • Decorator @staticmethod: Tells Python NOT to pass self or cls. It behaves like a plain function neatly grouped inside the class namespace.

9. Method Comparison Summary Table

Method TypeDecoratorFirst ArgumentAccess ScopePrimary Use Case
Instance MethodNoneselfInstance attributes (self.x) + Class attributesOperating on individual object data
Class Method@classmethodclsClass attributes (cls.x) onlyManaging class-wide state or alternative constructors
Static Method@staticmethodNoneNo access to self or clsUtility 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:

  1. Red arrow from s1 calling "s1.introduce()" pointing to Instance Data + Class Data.
  2. Purple arrow calling "Student.get_total_students()" going straight to Class Memory (cls).
  3. 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) receive cls and manipulate shared class state.
  • Static Methods (@staticmethod) are utility helper functions that operate without receiving self or cls.

What's Next?