CodeGym /Courses /Python SELF EN /The Power of Decorators

The Power of Decorators

Python SELF EN
Level 14 , Lesson 2
Available

6.1 Decorators for Class Methods

Decorators can also be used for class methods. It's important to remember to correctly pass the self or cls arguments for class methods.

We haven't covered the nuances of classes yet, but I'd like you to know that decorators can be used this way.


def log_method_call(func):
    def wrapper(self, *args, **kwargs):
        print(f"Method call {func.__name__}")
        return func(self, *args, **kwargs)

    return wrapper
        
class MyClass:
    @log_method_call
    def say_hello(self):
        print("Hello from MyClass!")
        
obj = MyClass()
obj.say_hello()

Explanation

Decorator (log_method_call): This decorator takes the method func and returns a new function wrapper that prints a message before calling the method.

Class method with decorator (say_hello): The say_hello method is wrapped with the log_method_call decorator, adding extra behavior when it's called.

Output:


Method call say_hello
Hello from MyClass!

6.2 Multiple Decorators

You can use multiple decorators for a single function, stacking them up. Decorators are applied in the reverse order of their declaration.


def decorator1(func):
    def wrapper():
        print("Decorator 1")
        func()

    return wrapper
        
def decorator2(func):
    def wrapper():
        print("Decorator 2")
        func()

    return wrapper
        
@decorator1
@decorator2
def say_hello():
    print("Hello!")
        
say_hello()

Explanation

Decorators (decorator1 and decorator2): These decorators add their messages before calling the function func.

Function with decorators (say_hello): The say_hello function is wrapped by both decorators. First, decorator2 is applied, then decorator1.

Output:


# Decorator 1
# Decorator 2
Hello!

6.3 Built-in Decorators

Python provides several built-in decorators for standard tasks, like static methods, class methods, and properties.

@staticmethod

The @staticmethod decorator is used to create a static method, which doesn't require a class instance to be called.


class MyClass:
    @staticmethod
    def static_method():
        print("This is a static method.")
        
MyClass.static_method()

@classmethod

The @classmethod decorator is used to create a class method, which takes the class (not instance) as its first argument.


class MyClass:
    @classmethod
    def class_method(cls):
        print(f"This is a class method {cls.__name__}.")
        
MyClass.class_method()

@property

The @property decorator is used to create getters, setters, and deleters for attributes.


class MyClass:
    def __init__(self, value):
        self.hidden_value = value
        
    @property
    def value(self):
        return self.hidden_value
        
    @value.setter
    def value(self, new_value):
        self.hidden_value = new_value
        
obj = MyClass(10)
print(obj.value)  # Output: 10
obj.value = 20
print(obj.value)  # Output: 20

These are built-in decorators, their proper functioning is ensured by the Python interpreter itself.

6.4 Examples of Using Decorators

Logging

Decorators can be used to log function and method calls.


def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__} with arguments {args} and {kwargs}")
        return func(*args, **kwargs)

    return wrapper
        
@log_call
def add(x, y):
    return x + y
        
print(add(2, 3))

Access Control

Decorators can be used to enforce access control to functions and methods.


def require_authentication(func):
    def wrapper(*args, **kwargs):
        if not args[0].is_authenticated:
            raise PermissionError("User is not authenticated.")
        return func(*args, **kwargs)
        
    return wrapper
        
class User:
    def __init__(self, is_authenticated):
        self.is_authenticated = is_authenticated
        
    @require_authentication
    def view_profile(self):
        print("User profile")
        
user = User(is_authenticated=True)
user.view_profile()  # Successful call
        
user2 = User(is_authenticated=False)
user2.view_profile()  # PermissionError: User is not authenticated.

Caching

Decorators can be used to cache function results.


def cache(func):
    cached_results = {}

    def wrapper(*args):
        if args in cached_results:
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        return result

    return wrapper

@cache
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(35))
2
Task
Python SELF EN, level 14, lesson 2
Locked
Multiple decorators.
Multiple decorators.
2
Task
Python SELF EN, level 14, lesson 2
Locked
Execution Duration.
Execution Duration.
Comments (3)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Wassim Tatari Level 17, TANGIER, Morocco
7 July 2026
It's a really difficult lesson.
luis_rmr Level 14, San Ramon, Costa Rica
10 August 2025
This and last lesson need better explalations
Wassim Tatari Level 17, TANGIER, Morocco
7 July 2026
True