DEV Community

Rohit Sanjay
Rohit Sanjay

Posted on

2 1

Decorator Factory - How to pass arguments to decorators

Skip to pass arguments to decorators if you already know what a decorator is

What is a decorator?

A decorator allows the user to add functionality to an existing function without modifying its structure.

For example,
We might need a way to authenticate an API call, and only then allow some data to be returned. We can streamline the authentication process by abstracting it into a decorator function.

Consider the following function that needs to be authenticated,

def foo(user_id):
   # perform some DB calls
   # perform some DB writes
   pass

We can use a decorator as follows,

def authenticate(func):
   def wrapper(*args, **kwargs):
       # perform auth checks
       if auth:
          func(*args, **kwargs)
       else:
          raise Exception('not authenticated')

   return wrapper

And hence, authenticating foo is as simple as,

@authenticate
def foo(user_id):
   # perform some DB calls
   # perform some DB writes
   pass

Pass arguments to decorators

Now that we have some knowledge of decorators, let us proceed to something more interesting. How would we pass arguments to decorators?

This is where it gets a little confusing - we will need to create a decorator factory that returns a particular decorator based on the arguments passed.

A simple use case could be when we want to call a function multiple times, but we do not want to write it in an explicit for loop, and neither do we want to use a for loop inside the function itself.

For example, we would want to call the function foo below, 10 times:

def foo():
   print("Hello World")

In this scenario, we can create a decorator factory that takes in a number and returns a decorator that calls a function a number of times.

def call(number):  # Decorator factory
    def decorator(func):
        def wraps(*args, **kwargs):
            for i in range(number):
                func(*args, **kwargs)

        return wraps

    return decorator

And to use the decorator factory above,

@call(10)
def foo():
   print("Hello World")

When we call foo now,

>>> foo()
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

Thanks for reading! Please hit me up at sanjay.rohit2@gmail.com for any feedback :)

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more