Introduction

In Python, decorators are a powerful feature that enables you to modify the behavior of a function or a class without changing its source code. Decorators are essentially functions that take another function as an argument and extend or modify the behavior of the latter function without explicitly changing it. Decorators can be used for a variety of purposes, from enhancing the performance of functions, adding logging, verifying access rights, and much more. This tutorial will introduce you to decorators in Python and show you how to harness their power to your advantage.

Table of Contents :

  • Decorators in Python
  • Python decorator example
  • Decorator definition
  • The @ symbol
  • wraps function

Decorators in Python :

  • In Python, a decorator is a special type of function that is used to modify another function. 
  • Decorators are typically used to add extra functionality to a function, or to change the way a function behaves. 
  • In Python, decorators are defined using the  symbol. 
  • a decorator takes another function and extends or modifies its behavior without modifying the original function's source code.
  • Decorators are a way of adding functionality to functions or classes, such as logging, timing, or authentication, without duplicating code.
  • Decorators can be defined for both functions and classes. 
  • When a decorator is defined for a class, it is applied to all of the class's methods. 
  • Decorators can take arguments. 
  • Decorators can be chained. That is, one decorator can be applied to a function that already has another decorator. 

Python decorator example :

  • Here is an example of a decorator that adds a "Hello, world!" message to a given function:
  • Code Sample :

def hello_decorator(func):
   def inner():
       print("Hello, world!")
       func()
   
   return inner

@hello_decorator
def hello():
   print("Greetings from the decorated function.")

hello()


# Output:
Hello, world!
Greetings from the decorated function.

Decorator definition :

  • To define a decorator, you need to define a function that takes another function as an argument and returns an inner function that extends or modifies the behavior of the passed-in function.
  • The inner function usually calls the passed-in function and performs additional actions before or after the call.
  • Here is a general syntax for defining a decorator:
  • Code Sample :

def my_decorator(func):
   def wrapper_func():
       # Do something before calling the decorated function
       result = func()
       # Do something after calling the decorated function
       return result
   
   return wrapper_func
   
   
   

The @ symbol :

  • In Python, the  symbol is used as shorthand for applying a decorator to a function.
  • Instead of calling a decorator function and passing in a function as an argument, you can simply place the  @ symbol followed by the decorator name above the function you want to decorate.
  • Code Sample :

@my_decorator
def my_function():
  pass
  
  
  

wraps function :

  • If you use a decorator function to modify a function's behavior, the modified function's signature may change. 
  • This can cause problems if other code relies on the function's original signature.
  • To avoid this issue, you can use the functools module's   wraps()  function 
  •   wraps()  function copies the original function's metadata (such as its docstring and signature) to the wrapper function.
  • Here is an example of using wraps to copy the original function's metadata to the wrapper function:
  • Code Sample :

import functools
def my_decorator(func):
   @functools.wraps(func)
   def wrapper_func(*args, kwargs):
       # Do something before calling the decorated function
       result = func(*args, kwargs)
       # Do something after calling the decorated function
       return result
   return wrapper_func
   
   
   

Prev. Tutorial : Closures

Next Tutorial : Decorators with arguments