Home > Software design >  Pass kwargs to function argument explictly
Pass kwargs to function argument explictly

Time:03-04

Is there a way in Python to pass explicitly a dictionary to the **kwargs argument of a function? The signature that I'm using is:

def f(*, a=1, **kwargs): pass # same question with def f(a=1, **kwargs)

I tried to call it the following ways:

my_dict=dict(b=2)
f(kwargs=my_dict) # wrong, kwargs receives {'kwargs': {'b': 2}} instead of {'b': 2}
f(**kwargs=my_dict) # SyntaxError: invalid syntax
f(kwargs=**my_dict) # SyntaxError: invalid syntax

The reason I want to do this is that the dictionary I pass in may contain the key a, and I don't want it to pollute the f's argument a:

overlap_dict=dict(a=3,b=4)
f(**overlap_dict) # wrong, 'a' is 3, and 'kwargs' only contains 'b' key
f(a=2, **overlap_dict) # TypeError: f() got multiple values for keyword argument 'a'

Replacing **kwargs with a dictionary in f's signature is not an option for me.

CodePudding user response:

Update the kwargs with a and then pass it. Example, say you have a value a=1, then do like this.

kwargs["a"] = a
f(**kwargs)

CodePudding user response:

Chage function defination to def f(a=1, /, **kwargs): pass

def f(a=1,/,  **kwargs): 
    print(a)
    print(kwargs)

overlap_dict=dict(a=3,b=4)
f(**overlap_dict)
# 1
# {'a': 3, 'b': 4}

CodePudding user response:

You can temporarily (or permanently, if you want – just remove the last line) modify f to take kwargs as a keyword argument. Note that this is a somewhat evil hack, so I would urge you to try other workarounds first.

import inspect


def f(*, a=1, **kwargs):
    print(a)
    print(kwargs)


code = f.__code__
f.__code__ = code.replace(
    co_kwonlyargcount=code.co_kwonlyargcount   1,
    co_flags=code.co_flags - inspect.CO_VARKEYWORDS,
)
f(kwargs={"a": 3, "b": 4})
f.__code__ = code

This prints:

1
{'a': 3, 'b': 4}
  • Related