In this lesson, we’ll learn about @classmethod . The @classmethod decorator is a neat feature in Python that lets you define methods tied to a class itself, not just its instances.
if you don’t know decorators yet, I have a lesson in Python Intermediate_006: Decorators in Python (https://medium.com/@staytechrich/python-intermediate-006-decorators-in-python-c7c7aaac7c8b) that’ll help you out. Let’s get started with some easy examples!
1. Basic @classmethod Example
Here’s a simple class method that greets you from the class level, not an instance:
class Greeter:
message = "Hello from the class!"
@classmethod
def say_hello(cls):
print("1. Inside class method: Accessing class data")
return cls.message
print("START")
result = Greeter.say_hello()
print(f"RESULT: {result}")
print("END")
Output:
START
1. Inside class method: Accessing class data
RESULT: Hello from the class!
END
Order of Execution
Let’s break it down step-by-step:
- @classmethod — Marks say_hello as a class method, passing cls (the class) instead of self.
- print(“START”) — Prints “START” before the call.
- result = Greeter.say_hello() — Calls the class method directly on Greeter.
- print(“1. Inside class method…”) — Runs inside say_hello, showing it’s active.
- return cls.message — Returns the class variable message (“Hello from the class!”).
- print(f”RESULT: {result}”) — Prints the returned value.
- print(“END”) — Prints “END”.
This is like a decorator wrapping a function, but here it shifts the focus to the class itself!
2. Practical Example: Instance Tracker
Now, let’s get practical. Imagine a class that tracks how many instances it’s created — perfect for debugging or stats. We’ll use @classmethod to report it.
class InstanceTracker:
count = 0
def __init__(self):
InstanceTracker.count += 1 # Bump count when an instance is made
@classmethod
def get_count(cls):
print("1. Inside class method: Checking instance count")
return f"Total instances: {cls.count}"
# Test it
print("START")
t1 = InstanceTracker()
t2 = InstanceTracker()
result = InstanceTracker.get_count()
print(f"RESULT: {result}")
print("END")
Output:
START
1. Inside class method: Checking instance count
RESULT: Total instances: 2
END
Order of Execution (for the full test)
- print(“START”) — Prints “START” before anything happens.
- t1 = InstanceTracker() — Creates the first instance, __init__ runs, count becomes 1.
- t2 = InstanceTracker() — Creates the second instance, count becomes 2.
- result = InstanceTracker.get_count() — Calls the class method.
- print(“1. Inside class method…”) — Runs inside get_count, showing it’s working.
- return f”Total instances: {cls.count}” — Returns “Total instances: 2” using cls.count.
- print(f”RESULT: {result}”) — Prints the result.
- print(“END”) — Prints “END”.
For an instance call (e.g., t1.get_count()), it works the same way — cls still refers to InstanceTracker!
3. Why @classmethod Rocks
- Class-Level Power: Access shared data (like count) without needing an instance.
- Factory Vibes: Use it for alternative constructors (more on that below).
Bonus Example: Factory Method
Here’s a quick factory method using @classmethod, like a mini-decorator trick:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_string(cls, data):
print("1. Inside class method: Parsing string")
name, age = data.split("-")
return cls(name, int(age))
print("START")
p = Person.from_string("Alice-30")
print(f"RESULT: {p.name}, {p.age}")
print("END")
Output:
START
1. Inside class method: Parsing string
RESULT: Alice, 30
END
Explanation Step by Step
1. What’s Happening When You Call Person.from_string(“Alice-30”)?
- Normally, to make a Person object, you’d write something like person1 = Person(“Alice”, 30). This calls the class directly with two arguments (name and age).
- But here, we’re using Person.from_string(“Alice-30”). This calls the @classmethod from_string instead of making the object right away. It’s a different way to create a Person.
2. Inside from_string(cls, data)
- The @classmethod decorator changes how this method works. Instead of getting self (which is for instances), it gets cls, which stands for the class itself — in this case, Person.
- data is the input you give when you call it. Here, data is the string “Alice-30”.
- The method’s job is to take that string, break it apart, and use it to make a Person object.
3. What data Does in from_string
- Inside from_string, data is the string “Alice-30” because that’s what we passed when we called Person.from_string(“Alice-30”).
- The line name, age = data.split(“-”) takes that string and splits it at the — into two parts:
- “Alice-30” → [“Alice”, “30”]
- Then, name gets “Alice”, and age gets “30”.
- int(age) turns the string “30” into the number 30 because age in __init__ expects a number, not a string.
- Finally, cls(name, int(age)) is like saying Person(“Alice”, 30) — it creates a new Person object using the class (cls) and returns it.
4. How It All Comes Together
- p = Person.from_string(“Alice-30”) calls the class method.
- data starts as “Alice-30”, gets split into name = “Alice” and age = “30”, and then makes a Person object with those values.
- p becomes a Person object with p.name = “Alice” and p.age = 30.
Wrap-Up
Try practicing more with InstanceTracker to log creation times or extend Person with more parsing options. Happy Coding!!
'Python Intermediate and Advanced' 카테고리의 다른 글
Python Intermediate_015_ Sorting with .sort() and Lambda in Python (0) | 2025.04.05 |
---|---|
Python Intermediate_014: Understanding @staticmethod in Python (0) | 2025.04.05 |
Python Intermediate_012:Python’s Magic Methods in Classes(Overview) (0) | 2025.04.05 |
Python Intermediate_011: Recursive Functions in Python (0) | 2025.04.05 |
Python Intermediate_010: Inheritance in Python (0) | 2025.04.05 |