A decorator in Python is a callable (function, method, or class) that allows us to modify or extend the behavior of another callable without permanently modifying it. Decorators are commonly used for tasks such as logging, enforcing access control and authentication, instrumentation and timing functions, rate-limiting, and caching; and they’re widely used in frameworks such as Flask and Django.
The decorator itself takes a function as an argument, and it returns a new function that includes the old function inside the closure. This new function usually includes some additional behavior before and/or after the old function is called. This is done by using the @ symbol before the decorator function and before the function you want to decorate.
Example:
```
def my_decorator(func):
def wrapper():
print(“Something is happening before the function is called.”)
func()
print(“Something is happening after the function is called.”)
return wrapper
@my_decorator
def say_hello():
print(“Hello!”)
```
In this example, `say_hello` is decorated by `my_decorator`. When you call `say_hello()`, it’s equivalent to calling `my_decorator(say_hello)()`. So it would print:
```
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
```