12

Is there a way to send more kwargs into a function than is called for in the function call?

Example:

def mydef(a, b):
    print a
    print b

mydict = {'a' : 'foo', 'b' : 'bar'}
mydef(**mydict)    # This works and prints 'foo' and 'bar'

mybigdict = {'a' : 'foo', 'b' : 'bar', 'c' : 'nooooo!'}
mydef(**mybigdict)   # This blows up with a unexpected argument error

Is there any way to pass in mybigdict without the error? 'c' would never be used in mydef in my ideal world and would just be ignored.

Thanks, my digging has not come up with what I am looking for.

Edit: Fixed the code a bit. The mydef(a, b, **kwargs) was the form that I was looking for, but the inspect function args was a new thing to me and definitely something for my toolbox. Thanks everyone!

8
  • 2
    The code you present is invalid, the first call blows up too. I think you want to remove the 2s in the keys. Commented Aug 23, 2012 at 14:20
  • Note that while you can do mydict = { 'a':'foo', 'b':'bar' } and pass that to mydef(**dict). Using dicts and (non)keyword arguments this way is not common. You'll sometimes see if it you defined mydef with default arguments : mydef(a=None, b=None), but rarely will you see it passed that way with regular arguments ... With regular arguments, you'll more frequently see: mytuple = ('foo','bar') and then the call uses the (single) splat operator: mydef(*mytuple) Commented Aug 23, 2012 at 14:26
  • 1
    @mgilson: using a keyword syntax for positional arguments is perfectly legal and useful at times. Commented Aug 23, 2012 at 14:28
  • @MartijnPieters -- I didn't say it was illegal (I said that it isn't common). Even accessing positional arguments by keyword I can see (a little bit). However, unpacking a dictionary for positional arguments I can't see a use for. It's simply unclear what the function is receiving (in my opinion) -- Would you do this with dicts instead of tuples? I haven't come across a case where I would ... Commented Aug 23, 2012 at 14:31
  • 1
    @deadstump -- In my workflow, I pass tuples to positional arguments, and I pass dicts to default and keyword arguments. So, a typical function call of mine might look like: myfunc(*mytuple,**mydict) where func is defined: def func(a,b,c=2,**kwargs): and mytuple might be (1, 2). Apparently some people might do it differently (as you have been doing it) and MartijnPieters corroborates. You're right that with tuples, the order matters and the order is the order that you would pass the arguments to the positional arguments in the underlying function. Commented Aug 23, 2012 at 15:07

2 Answers 2

21

No, unless the function definition allows for more parameters (using the **kwargs catch-all syntax), you cannot call a method with more arguments than it has defined.

You can introspect the function and remove any arguments it won't accept however:

import inspect

mybigdict = {'a2' : 'foo', 'b2' : 'bar', 'c2' : 'nooooo!'}
sig = inspect.signature(mydef)
if not any(p.kind == p.VAR_KEYWORD for p in sig.parameters.values()):
    for missing in mybigdict.keys() - sig.parameters.keys():
        del mybigdict[missing]
mydef(**mybigdict)

I'm using the inspect.signature() function to check if the callable supports a **kwarg catch-all (by looking for a Parameter.VAR_KEYWORD entry), and if it doesn't, I use the set difference between mybigdict and the signature .parameters mapping to remove anything the method won't support.

Sign up to request clarification or add additional context in comments.

3 Comments

I was considering suggesting to add some **kwargs in the definition of mydef, but I think you'll agree it's a false good idea: there's no way to ensure the order of the arguments...
The inspect method will modify your mybigdict, though, which may have some undesirable side-effects.
@PierreGM: It's easy enough to make a copy, isn't it? I'm trying to illustrate a technique in a reasonably concise manner, not cover all eventualities here.
10

To clarify Martijn Pieters's answer (for sake of clarity). It's possible if you change the function signature to:

def mydef(a, b, **kwargs):

This means it's not possible without changing the signature. But if that's not a problem it'll work.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.