Decorators give us a way to work with functions, including modifying the working of a function. A decorator starts with the @ before the decorator’s name above the function definition.

@greeting
def greetings():
    print('Welcome!')

Now, the greetings() function has a greeting decorator and whenever the greetings() function is called, the decorator is also called. If we take a closer look at a decorator, it is basically a function in which another function is passed into it as a parameter and is wrapped and returns the function that was passed. Let’s use the above example to explain what was just written:

def greeting(func): # The decorator which takes the function as a parameter
    def wrapper():  # The wrapper function
        a = func() # The function that was passed and is now contained within the wrapper function

        return a # Return the variable 'a' which points to the function
    return wrapper # Return the wrapper function