🧠 Python Functions and Functional Programming
Estimated reading: 3 minutes 35 views

🧩 Python Decorators – Wrap, Enhance, and Reuse Functions

🧲 Introduction – What Are Python Decorators?

In Python, decorators are a powerful feature that lets you modify or extend the behavior of a function or classβ€”without changing its actual code.

They are commonly used for logging, authentication, timing functions, and more. Python decorators leverage closures and higher-order functions, making them a go-to tool for writing cleaner, DRY (Don’t Repeat Yourself) code.

🎯 In this guide, you’ll learn:

  • What decorators are and how they work
  • How to define and apply decorators
  • The role of @ syntax and functools.wraps
  • Real-world examples and best practices

πŸ”§ What Is a Decorator?

A decorator is a function that takes another function as input and returns a new function that usually enhances or wraps the original.

def decorator(func):
    def wrapper():
        print("Before function runs")
        func()
        print("After function runs")
    return wrapper

βœ… Applying a Decorator

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

say_hello()

🧠 Output:

Before function runs  
Hello!  
After function runs

πŸ“˜ Explanation:
The @decorator is shorthand for say_hello = decorator(say_hello).


πŸ“¦ Real-World Decorator Example: Logger

def logger(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__} with {args} and {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@logger
def greet(name):
    return f"Hello, {name}"

print(greet("Alice"))

🧠 Using *args and **kwargs in Decorators

Use *args and **kwargs to accept functions with any number of arguments, keeping your decorators reusable and flexible.


βš™οΈ functools.wraps – Preserve Metadata

from functools import wraps

def smart_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Decorated function running...")
        return func(*args, **kwargs)
    return wrapper

βœ… Always use @wraps(func) inside decorators to preserve:

  • Function name
  • Docstring
  • Signature

πŸ” Chaining Multiple Decorators

@decorator1  
@decorator2  
def my_func():
    pass

Python applies them bottom-up, so decorator2 wraps my_func, and then decorator1 wraps the result.


πŸ§ͺ Built-in Decorators You Should Know

DecoratorPurpose
@staticmethodDefine a method without self
@classmethodTakes cls instead of self
@propertyMake method behave like an attribute

⚠️ Common Pitfalls

MistakeFix
Not returning wrapper()Always return the nested function
Forgetting @wrapsUse @wraps(func) to retain metadata
Not using *args, **kwargsNeeded for flexibility in decorators

πŸ’‘ Best Practices

  • βœ… Always use functools.wraps inside decorators
  • βœ… Use decorators for cross-cutting concerns like logging, validation, caching
  • βœ… Keep decorators small and focused
  • ⚠️ Avoid complex logic inside decoratorsβ€”prefer clarity over cleverness

πŸ“Œ Summary – Recap & Next Steps

Python decorators are a clean and elegant way to enhance or modify function behavior without changing their code. By using closures and higher-order functions, decorators help build flexible, maintainable, and reusable components.

πŸ” Key Takeaways:

  • βœ… Decorators wrap functions using the @decorator syntax.
  • βœ… *args and **kwargs allow decorators to work with any function signature.
  • βœ… Use functools.wraps to retain original function metadata.
  • βœ… Great for logging, timing, authentication, and more.

βš™οΈ Real-World Relevance:
Decorators are widely used in Flask/Django, unit testing, and API rate-limiting, allowing clean and modular code enhancements across production-grade applications.


❓ FAQ Section – Python Decorators

❓ What is a decorator in Python?

βœ… A decorator is a function that wraps another function to extend or modify its behavior without altering the function’s code directly.

❓ How do I create a custom decorator?

βœ… Define a function that takes another function as an argument and returns a wrapper function:

def decorator(func):
    def wrapper():
        return func()
    return wrapper

❓ Why use *args and **kwargs in decorators?

βœ… To ensure your decorator works with functions of any number of positional and keyword arguments.

❓ What does @functools.wraps do?

βœ… It preserves the metadata (like name, docstring, signature) of the original function, making debugging and introspection easier.

❓ Can I use multiple decorators on one function?

βœ… Yes. Decorators are stacked from bottom to top and applied in that order:

@first
@second
def func():
    pass

Share Now :

Leave a Reply

Your email address will not be published. Required fields are marked *

Share

Python Decorators

Or Copy Link

CONTENTS
Scroll to Top