0

So I was trying out the *args and **kwargs in Python. But I get an error that I cannot understand the reason of.

def new(a,b,c):
  print a,b,c

a={'a': 7, 'b': 8, 'c': 9}
b={'1':7, '2':8, '3':9}

new(**a)
new(**b)

The new(**a) prints the results as expected, that is, the keys, 7,8,9. But, new(**b) gives the error:

new(**b)
TypeError: new() got an unexpected keyword argument '1'

Could anyone explain this? I am passing string as an argument in both cases, but 'a' works and '1' doesn't.

5
  • Variables cannot be numbers, which means your dictionary keys should not start with one. Commented Oct 6, 2016 at 2:14
  • 2
    If you think about the fact that new(**a) is essentially new(a=7, b=8, c=9), you can probably figure out why it does not work. Commented Oct 6, 2016 at 2:15
  • @Nicarus There are two problems here. That is definitely one, but that's not what Python is choosing to raise as the error. Commented Oct 6, 2016 at 2:16
  • 1
    The function you defined doesn't (and couldn't possibly) take arguments named 1, 2, or 3. Commented Oct 6, 2016 at 2:25
  • Possible duplicate of What does ** (double star) and * (star) do for Python parameters? Commented Oct 6, 2016 at 4:11

3 Answers 3

1

The reason is simple. When you pass a dictionary to a python function as kwargs it unpacks that and uses the keys in the dictionary as the names of the variables and you can **only use parameter names that you have specified in the function parameters list.

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

3 Comments

I'd like to clarify that it is not just that the OP used numbers. This would have still failed if they tried to use the keys 'd', 'e', and 'f'.
See my answer - you can have numeric kwargs
Actually @LegoStormtroopr, I am refering the keys, not the values. and the user did in fact not send number keys but stings of numbers.
0

for a dictionary data={"key1":val1, "key2":val2, ..., "keyn":valn} when you do dictionary unpacking in a function call, fun(**data), is equivalent to doing fun(key1=val1, key2=val2,..., keyn=valn) and this will success as long as your function had arguments key1,...,keyn and/or accept keyword arguments.

So the problem with new(**b) is that is trying to do new(1=7,2=8,3=9) which is a nonsense as the function only had arguments named a,b,and c, therefore the error.

For your, your second example try with list instead

b=[7,8,9]
new(*b)

Also, you may want to play around with this function

def test(*argv, **kwarg):
    print "positional arguments", argv
    print "key word arguments", kwarg

like for instance

test(1,23,42)
test(w=3,r="buu")
test(1,2,3,q=23,ans=42)
a=[143,56,76]
b={'a': 7, 'b': 8, 'c': 9}
test(*a,**b)

Comments

0

This is related to a similar question, but in short passing **kwargs to a method is a way to pass in a number of key word arguments as a dictionary.

The reason your attempt fails is that your method new defines 3 named arguments - a,b,c so if you pass in a kwargs dictionary it must have these values as keys.

Its important to note that you can also catch kwargs in the method so you can call a method with numeric arguments, like so:

def foo(**kwargs):
    print kwargs

a={'a': 7, 'b': 8, 'c': 9}
b={'1':7, '2':8, '3':9}

foo(**a)
foo(**b)

Gives:

{'a': 7, 'c': 9, 'b': 8}
{'1': 7, '3': 9, '2': 8}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.