Search code examples
pythondecoratorkeyword-argument

How to properly get default keyword arguments for decorators?


I'm applying a decorator to some functions, and the decorator would require some arguments in the functions. Yet, I would assign some default values to the arguments. The decorator receives the arguments with *args, **kwargs.

def decorator(fn):
    def wrapper(*args, **kwargs):
        print(args)
        print(kwargs)
        # do something with the required1 and required2 ...
        return fn(*args, **kwargs)
    return wrapper

class MyClass(object):
    def foo(self, a, b, required1=0, required2='x'):
        pass

But calling the function in differernt ways the decorator wrapper would receive different argumets

A = MyClass()
A.foo(1, 2, 3, '4') # 1
A.foo(1, 2) # 2
A.foo(1, 2, required1=3, required2='4') # 3

The outputs would be like such:

#1 
args: [<object at 0x0000>, 1, 2, 3, ‘4’]
kwargs: {}
#2
args: [<object at 0x0000>, 1, 2]
kwargs: {}
#3
args: [<object at 0x0000>, 1, 2]
kwargs: {‘required1’: 3, ‘required2’: ‘4’}

How am I supposed to do if I want to access the required arguments like r = kawrgs[‘required1’] no matter the way of calling the function?


Solution

  • I've tried to solve this problem in one of my projects. And the only way I found is to use introspection of python.

    Here is the code:

    bound_args = inspect.signature(fn).bind(*in_args, **in_kwargs)
    bound_args.apply_defaults()
    target_args = dict(bound_args.arguments)
    

    its binding income arguments of the function (either it comes with keywords or not) to the defined names of the function