Search code examples
pythondictionaryunpackargument-unpacking

Unpack multiple dictionaries as functional arguments without repeating double asterisk


I use API with long name of argument parameters. Consequently, I create following dictionaries for most common combinations of values which are then unpacked in function calls.

a_T = {'API parameter a': True}
a_F = {'API parameter a': False} 
b_100 = {'API parameter b': 100}
b_0 = {'API parameter b': 0}
hello = {'API parameter c': 'hello'}
bye = {'API parameter d': 'goodbye'}    

myf(**a_T, **bye)
myf(**b_0)
myf(**a_F, **b_100, **hello, **bye)

Is there any way to avoid repeat double asterisk? The code becomes quite unreadable with many of these strange characters.

Once could then add this unpacking utility to myf:

myf(a_T, bye)
myf(b_0)
myf(a_F, b_100, hello, bye)

Solution

  • You can actually use | for Python 3.9+ to combine all the dictionaries then send unpacked version.

    def fun(**kwargs):
        print(kwargs)
    
    >>> fun(**a_F| b_100| hello| bye)
    {'API parameter a': False, 'API parameter b': 100, 'API parameter c': 'hello', 'API parameter d': 'goodbye'}
    

    Or just use *args and pass multiple dictionaries:

    def fun(*args):
        print(args)
        
    >>> fun(a_F,b_100,hello,bye)
    ({'API parameter a': False}, {'API parameter b': 100}, {'API parameter c': 'hello'}, {'API parameter d': 'goodbye'})
    

    Another solution is to use Python decorator and take care of ugly part inside the decorator function:

    def decorator(fun):
        def wrapper(*args):
            from functools import reduce
            kwargs = reduce(lambda a, b: a | b, args)
            return fun(**kwargs)
        return wrapper
    @decorator
    def main_fun(**kwargs):
        print(kwargs)
        
    
    >>> main_fun(a_F,b_100,hello,z)
    {'API parameter a': False, 'API parameter b': 100, 'API parameter c': 'hello', 'parameter 4': 'goodbye'}