nven
nven

Reputation: 1207

Multiple kwargs in a function call?

I have a simple function which is called like this:

arbitrary_function(**kwargs1, **kwargs2, **kwargs3)

It seems to compile fine on my local installation (python 3.5.1) but throws a SyntaxError when I compile it on a docker with python 3.4.5.

I'm not too sure why this behavior is present. Are multiple kwargs not allowed? Should I combine them before passing to function? It is more convenient to pass them individually, for example:

plot(**x_axis_params, **y_axis_params, **plot_params)

instead of

params = dict()

for specific_param in [x_axis_params, y_axis_params, plot_params]:    
    params.update(specific_param)

plot(**params)

Upvotes: 13

Views: 16940

Answers (4)

Mitchell Miller
Mitchell Miller

Reputation: 29

Based on @egorauto 's answer, , I applied egorauto's approach to Kwargs and found it to be much more 'handy' the other ways like using a for key,value in kwargs.items() loop clause / etc. In retrospect, this seems obvious, but for some reason I just hadn't tried it. Since it helped me I'm posting here too.

e.g.,

def test(name,**kwargs):
    typex = kwargs['typex']
    adjective = kwargs['adjective']
    
    if typex == 'cat':
        print(f"{name} is a {adjective} {typex}.")
        
    elif typex == 'human':
        gender = kwargs['gender']
        
        print(f"{name} is a {adjective} {gender}.")
        
    

        

this easily accomodates calling the minimum necessary kwargs for the context:

test(name='meowsie',typex='cat',adjective='cool')

"meowsie is a cool cat"

or

test(name='john',typex='human',adjective='young',gender='boy')

"john is a young boy"

Sorry I didn't adapt the example specifically to OP, but I had to rush. I think its clear to see you would use 'x_axis_param' instead of typex, 'y_axis_param' instead of adjective, etc.

Upvotes: 0

egorauto
egorauto

Reputation: 21

You can use *args instead, e.g.:

plot(*[x_axis_params, y_axis_params, plot_params])

And then within the function:

def plot(*args):
    x_axis_params = args[0]
    y_axis_params = args[1]
    plot_params   = args[2]
return None

If you want several **kwargs when e.g. initialising class attributes then you can also do something like self.__dict__.update(**x_axis_params)

Upvotes: 2

ali_m
ali_m

Reputation: 74154

One workaround mentioned in the rationale for PEP448 (which introduced that Python feature) is to use collections.ChainMap:

from collections import ChainMap

plot(**ChainMap(x_axis_params, y_axis_params, plot_params))

ChainMap was introduced in Python 3.3, so it should work in your docker instance.

Upvotes: 1

user2357112
user2357112

Reputation: 280236

That's a new feature introduced in Python 3.5. If you have to support Python 3.4, you're basically stuck with the update loop.

People have their own favored variations on how to combine multiple dicts into one, but the only one that's really a major improvement over the update loop is 3.5+ exclusive, so it doesn't help with this. (For reference, the new dict-merging syntax is {**kwargs1, **kwargs2, **kwargs3}.)

Upvotes: 10

Related Questions