Python Advanced Concepts Decorators Tutorial
Intermediate Level Meta-programming

Python Decorators: Complete Guide with Examples

Master Python decorators - powerful tools that modify functions and classes. Learn @ syntax, create custom decorators, and apply them in real-world scenarios.

@ Syntax

Clean decorator syntax

20+ Examples

Practical decorator patterns

Function & Class

Both types covered

Real Applications

Web, Logging, Caching

What is a Decorator?

A decorator is a function that modifies or extends the behavior of another function without changing its original code.

Decorators are widely used in:

  • Logging
  • Authentication
  • Timing
  • Validation
  • Frameworks like Django and Flask

Real-Life Example

Imagine decorating a room:

  • Original room remains same
  • Decorations add extra features

Similarly:

  • Original function remains same
  • Decorator adds extra functionality

Functions are First-Class Objects

In Python, functions can be stored in variables, passed as arguments, and returned from other functions.

Example:

def greet():
    print("Hello")

msg = greet
msg()

Output: Hello

Basic Decorator Structure

def decorator_function(original_function):
    def wrapper():
        print("Before function call")
        original_function()
        print("After function call")
    return wrapper

Applying Decorator Manually

def decorator_function(original_function):
    def wrapper():
        print("Before execution")
        original_function()
        print("After execution")
    return wrapper

def display():
    print("Display function")

decorated = decorator_function(display)
decorated()

Output:
Before execution
Display function
After execution

Using @ Decorator Syntax

Python provides cleaner syntax using @.

def decorator_function(original_function):
    def wrapper():
        print("Before execution")
        original_function()
        print("After execution")
    return wrapper

@decorator_function
def display():
    print("Display function")

display()
How @ Syntax Works
@decorator
def test():
    pass

is equivalent to:

test = decorator(test)

Decorator with Arguments

Use *args and **kwargs.

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        print("Before function")
        original_function(*args, **kwargs)
        print("After function")
    return wrapper

@decorator_function
def add(a, b):
    print(a + b)

add(10, 20)

Output:
Before function
30
After function

Returning Values from Decorator

def decorator_function(original_function):
    def wrapper(*args, **kwargs):
        result = original_function(*args, **kwargs)
        return result
    return wrapper

@decorator_function
def square(n):
    return n * n

print(square(5))

Output: 25

Multiple Decorators

def decor1(func):
    def wrapper():
        print("Decorator 1")
        func()
    return wrapper

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

@decor1
@decor2
def show():
    print("Show function")

show()

Output:
Decorator 1
Decorator 2
Show function

Built-in Decorators

Python provides built-in decorators such as:

DecoratorPurpose
@staticmethodStatic method
@classmethodClass method
@propertyGetter method
@staticmethod Example
class Demo:
    @staticmethod
    def show():
        print("Static method")

Demo.show()
@classmethod Example
class Student:
    school = "ABC School"

    @classmethod
    def display(cls):
        print(cls.school)

Student.display()
@property Example
class Employee:
    def __init__(self, salary):
        self.__salary = salary

    @property
    def salary(self):
        return self.__salary

e = Employee(50000)
print(e.salary)

Output: 50000

Timing Decorator Example

import time

def timer(func):
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print("Execution Time:", end - start)
    return wrapper

@timer
def test():
    for i in range(1000000):
        pass

test()

Login Authentication Decorator

def login_required(func):
    def wrapper(user):
        if user == "admin":
            func(user)
        else:
            print("Access denied")
    return wrapper

@login_required
def dashboard(user):
    print("Welcome", user)

dashboard("admin")

Advantages of Decorators

  • Code reusability
  • Cleaner code
  • Easy maintenance
  • Adds functionality dynamically
  • Reduces repetition

Disadvantages of Decorators

  • Harder to debug sometimes
  • Nested decorators can confuse beginners

Real-Life Uses

Use CaseExample
AuthenticationLogin systems
LoggingTrack function calls
PerformanceMeasure execution time
ValidationInput checking
Web frameworksRoute handling

Decorators vs Normal Functions

Normal FunctionDecorator
Performs task directlyEnhances another function
IndependentWraps existing function
Next Topics: We'll cover Python Generators and Context Managers