How to detect missing arguments in decorator?

I would like to define a decorator with a parameter that raises an error if the parameter is missing.

Here’s a naive attempt on a simplified example:

def decorator_with_arg(a=None):

    if a is None :
        raise ValueError("Missing argument in decorator")

    def decorator(func):

        def wrapped_func(x):
            return func(x+ a)

        return wrapped_func

    return decorator

But when I use this decorator without a parameter it’s not raising any errors:

@decorator_with_arg
def simple_func(x):
    return 2*x

simple_func(1)

How can I raise an error?

>Solution :

You are not using your decorator correctly, in your code simple_func(1) will just return wrapped_func, because @decorator_with_arg will simply do:

simple_func = decorator_with_arg(simple_func)
#                                ^ this is passing a=simple_func
# now simple_func is the decorator function defined inside decorator_with_arg

You need to call your decorator_with_arg in order for it to return decorator which will then be used to decorate the function:

@decorator_with_arg(100)
def simple_func(x):
    return 2*x

print(simple_func(1)) # 202

In any case, if you want to make an argument mandatory, simply declare it without a default value:

def decorator_with_arg(a):
    # ...

And remove the if a is None check.


If you want to avoid mistakes in using @decorator_with_arg instead of @decorator_with_arg(), you can add a check to ensure a is not a function:

def decorator_with_arg(a):
    if callable(a):
        raise TypeError("Incorrect use of decorator")
    
    def decorator(func):
        def wrapped_func(x):
            return func(x + a)
        return wrapped_func
    return decorator


@decorator_with_arg
def func():
    return 1
# TypeError: Incorrect use of decorator


@decorator_with_arg(123)
def func():
    return 1
# All fine

Leave a Reply