← Back to list

Python — Decorators, @classmethod, @staticmethod & the Three Types of Python Methods

Python functions can wrap other functions — and that a class has three completely different types of methods, each with a different…

Anuj Chhetri · 2026-04-10 15:49 · 1 claps · 3.7 min read
#python #oop-concepts #decorators #class-method #static-methods
Open on Medium ↗

Python — Decorators, @classmethod, @staticmethod & the Three Types of Python Methods

Python functions can wrap other functions — and that a class has three completely different types of methods, each with a different purpose.

Part 1 — Decorator

What Is a Decorator?

A decorator is a function that:

Takes another function as its argument

Wraps it — adds behavior before and/or after it runs

Returns a new function (the wrapper)

Decorator -> is a function
argument  -> it takes a function
def my_fun(func): here func is source code
                  we do NOT change the original code
                  we EXTEND its functionality

Think of it like a gift wrapper. The gift (original function) stays the same inside. The wrapper (decorator) adds presentation around it.

How It Works — Step by Step

def my_decorator(xyz):         # xyz = the original function being decorated
    def wrapper():
        print("Hello 1")       # runs BEFORE the original function
        xyz()                  # calls the original function
        print("Hello 3")       # runs AFTER the original function
    return wrapper             # returns the new wrapped function

@my_decorator                  # applies the decorator
def hello_counter():
    print("Hello 2 ")

hello_counter()

# Output:
# Hello 1
# Hello 2
# Hello 3

What @my_decorator does: Writing @my_decorator above a function is exactly the same as writing:

hello_counter = my_decorator(hello_counter)

Python passes hello_counter into my_decorator, and replaces it with the returned wrapper.

Another Example:

def repeat(func):
    def wrapper(value):
        for i in range(3):
            func(value)
    return wrapper

@repeat
def greet(name):
    print(f"Hello, {name}!")

greet("Ram")

# Output
# Hello, Ram!
# Hello, Ram!
# Hello, Ram!

When Are Decorators Used in Real Life?

**@classmethod and `@staticmethod`** — built-in Python decorators (covered below)

**@property** — turns a method into an attribute

Timing — measure how long a function takes

Logging — track every function call automatically

The Three Types of Methods in a Class:

Every method inside a class falls into one of three categories. Understanding the difference is essential for writing clean OOP code.

Method Type       Decorator      First Parameter        Accesses
Instance method    (none)          self              Instance data + class data
Class method       @classmethod    cls               Class data only
Static method      @staticmethod   (none)            Neither — utility only

Instance Method

The most common type. Takes self as the first parameter, giving it access to the specific object's data.

class Cat:
    def __init__(self, name, age):
        self.name = name
        self.age  = age

    def describe(self):              # instance method
        return f"{self.name} is {self.age} years old"

    def voice(self, sound):          # instance method with extra param
        return f"{self.name} says {sound}"

cat1 = Cat("Merry", 1)
cat1.describe()           # 'Merry is 1 years old'
cat1.voice("Meow")        # 'Merry says Meow'

Instance methods work with self — the specific object that called them.

Class Method

What Is a Class Method?

A class method is a method that:

Uses **@classmethod decorator**

Takes **cls** (the class itself) as the first parameter — not self

Can access and modify class attributes that are shared across all objects

Is called on the class itself, not on an object: ClassName.method()

@classmethod decorator
Factory method creation
cls -> refers to the class itself (like self refers to the object)
class Customer:
    total_customer       = 0    # class attribute — shared
    total_customer_spent = 0    # class attribute — shared

    def __init__(self, name, amount_spent):
        self.name         = name
        self.amount_spent = amount_spent
        Customer.total_customer       += 1           # update class attr
        Customer.total_customer_spent += amount_spent  # update class attr

    # Instance method — works on one customer
    def customer_details(self):
        return f"The name of the customer is {self.name} and s/he has spent NPR {self.amount_spent}"

    # Class method — works on ALL customers
    @classmethod
    def get_total_customer(cls):
        return f"Total number of customer is {cls.total_customer}"

    # Class method — calculates class-level statistic
    @classmethod
    def avg_customer_spent(cls):
        return f"Total average spent by the customer is {cls.total_customer_spent / cls.total_customer:.2f}"

customer1 = Customer("Ram",   1000)
customer2 = Customer("Gita",  2500)
customer3 = Customer("Shyam",  500)

total = Customer.get_total_customer()
avg   = Customer.avg_customer_spent()

print(total)    # Total number of customer is 3
print(avg)      # Total average spent by the customer is 1333.33

Notice: Customer.get_total_customer() is called on the class, not on any specific customer object. It knows about all three customers because it accesses the class attribute total_customer.

Static Method

What Is a Static Method?

A static method is a method that:

Uses **@staticmethod decorator**

Takes no implicit first argument — no self, no cls

Cannot access or modify class or instance state

Is just a regular utility function that lives inside the class for organizational purposes

@staticmethod decorator
does not take any implicit first argument (like self, cls)
Cannot access or modify the class state
class Customer:

    def __init__(self, name, amount_spent):
        self.name         = name
        self.amount_spent = amount_spent

    def customer_details(self):
        return f"The name of the customer is {self.name} and s/he has spent NPR {self.amount_spent}"

    @staticmethod
    def is_valid_account_type(account_type):
        valid_account_type = ["Coffee products", "Tea Products", "Bakery Products"]
        return account_type in valid_account_type    # returns True or False

    @staticmethod
    def addition(x, y, z):     # pure utility — no class/instance data needed
        return x + y + z

Customer.is_valid_account_type("Coffee products")    # True
Customer.is_valid_account_type("Dairy")              # False

Customer.addition(2, 3, 4)     # 9

The is_valid_account_type method doesn't need to know about any specific customer. It just validates whether a type is in the allowed list — pure logic. That's what static methods are for.

Instance Method vs @classmethod vs @staticmethod

class Employee:
    company = "MY COMPANY"    # class attribute

    def __init__(self, name, salary):
        self.name   = name
        self.salary = salary

    # INSTANCE METHOD — accesses this specific employee
    def get_details(self):
        return f"{self.name} earns {self.salary}"

    # CLASS METHOD — accesses company-level data
    @classmethod
    def get_company(cls):
        return f"Company: {cls.company}"

    # STATIC METHOD — pure utility, no company/employee data needed
    @staticmethod
    def is_valid_salary(salary):
        return salary > 0

emp1 = Employee("Ram", 50000)
emp2 = Employee("Gita", 75000)

# Instance method — called on object
emp1.get_details()            # Ram earns 50000

# Class method — called on class
Employee.get_company()        # Company: MY COMPANY

# Static method — called on class (or object, both work)
Employee.is_valid_salary(50000)    # True
Employee.is_valid_salary(-1000)    # False

메타데이터
post_id
b7f65e5e9f8f
slug
python-decorators-classmethod-staticmethod-the-three-types-of-python-methods-b7f65e5e9f8f
url
https://medium.com/@dotsyko/python-decorators-classmethod-staticmethod-the-three-types-of-python-methods-b7f65e5e9f8f
canonical_url
https://medium.com/@dotsyko/python-decorators-classmethod-staticmethod-the-three-types-of-python-methods-b7f65e5e9f8f
author_url
https://medium.com/@dotsyko
status
ok
fetched_at
2026-06-13 09:11:36