coding180 icon
Coding180
Decorators in Python Functions

Decorators in Python Functions

Home > Tutorials > Python for beginners > Functions


Decorators are functions that modify the behavior of other functions or classes without changing their code.

Why Are Decorators Useful?

Decorators can be incredibly useful because they help you add more functionality to your existing code without cluttering it up with additional lines of code. You can think of decorators as a way to "wrap" your function in some extra capabilities, making it more powerful and easier to use.

How to Create and Apply Decorators

Creating a decorator is easy – you just define a new function that takes another function as its input, modifies it in some way (e.g., adds new features), and then returns the modified function. Here's an example:

def my_decorator(func):
    def wrapper():
        print("Before the function is called.")
        func()
        print("After the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

In this example, my_decorator is a function that takes another function (func) as its input, defines a new function (wrapper) that modifies the input function, and then returns the modified function. We then apply the decorator to our say_hello function using the @my_decorator syntax.

When we call say_hello(), the output will be:

Before the function is called.
Hello!
After the function is called.

As you can see, the my_decorator function has added some extra behavior to our say_hello function.

Real-World Examples of Decorators

One common use case for decorators is timing how long a function takes to run. Here's an example:

import time

def timing_decorator(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print("Time taken:", end_time - start_time, "seconds")
    return wrapper

@timing_decorator
def my_function():
    time.sleep(2)

my_function()

In this example, our timing_decorator function uses the time module to measure how long it takes for the input function to run. We then apply the decorator to our my_function function and call it.

When we call my_function(), the output will be:

Time taken: 2.000783920288086 seconds

Another common use case for decorators is caching – that is, storing the result of a function so that future calls with the same inputs can be returned quickly without needing to recalculate the answer. Here's an example:

cache = {}

def cache_decorator(func):
    def wrapper(n):
        if n in cache:
            return cache[n]
        result = func(n)
        cache[n] = result
        return result
    return wrapper

@cache_decorator
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))

In this example, our cache_decorator function checks if the input (n) is already stored in the cache dictionary. If it is, we simply return the cached value. Otherwise, we calculate the result and store it in the cache dictionary before returning it.

When we call fibonacci(30), the output will be the value of the 30th number in the Fibonacci sequence (which is 832040). Because we have used a caching decorator, this result was calculated very quickly – even though calculating the 30th Fibonacci number using brute force would be very slow.

Conclusion

Decorators are a powerful tool in Python that allows you to modify the behavior of functions and classes without actually changing their code. They can be used for a wide range of purposes, from timing and caching to error handling and beyond. By mastering decorators, you can add new features to your Python code with ease. 


user

Robort Gabriel

Lagos, Nigeria

Freelance Web Developer, Native Android Developer, and Coding Tutor.

Skills
  • UI / UX
  • JavaScript
  • Python
  • PHP
  • Kotlin
  • Java
  • Bootrap
  • Android
  • Laravel