-1

I have a seemingly easy question which I can't find an answer to. With a simple function such as the following:

def test_kwargs_1(a,**kwargs):
    print a
    print b

I was thinking that, if I passed:

kwargs = {'a':1,'b':2}
test_kwargs_1(**kwargs)

it would print:

1
2

as it would unpack "kwargs" and both a variable "a" and "b" would be available. Instead i get:

1
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
.
.
----> 3     print b
NameError: global name 'b' is not defined

I understand that "b" is a variable which may or may not exist, but I thought that the unpacking of kwargs would make the variable "b" available if explicitly defined in kwargs. What am I not getting? Thanks, s

serrajo
  • 231
  • 4
  • 10
  • `b` is not declared in you function `test_kwargs_1`, as the error says. The way of accessing undefined `kwargs` in a function is threating it as a dictionary: `kwargs['b']`. – Imanol Luengo Feb 26 '16 at 12:14
  • Possible duplicate of [What does \*\* (double star) and \* (star) do for Python parameters?](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters) – GingerPlusPlus Feb 26 '16 at 12:44
  • Thanks for the reply. This is the explanation that I gave to myself but I find it a bit illogical. I thought that passing **kwargs, indipendently on if a variable is declared or not, would unpack what's in the kwargs dictionary and effectively do "a=1" and "b=2". It actually does "a=1", as print(a) works, while "b" remains a key of the dictionary and needs to be accessed. I understand how a function should give warnings (as "b" may be not passed), but it seems to me it is doing 2 different things according on if a argument is positional or not – serrajo Feb 26 '16 at 13:13

1 Answers1

6

Using **kwargs in your function definition means that you can take any number of keyword arguments, and you will store them all in the dictionary called kwargs. You can use kwargs['b'] instead of b.

zondo
  • 19,901
  • 8
  • 44
  • 83
  • Thanks for the reply. What surprises me is that with the "a" argument it actually does what I expected (i.e. the variable "a" is available, even if passed through the dictionary kwargs, while "b" is not). It seems to me it does two different things depending on if a variable is positional or not – serrajo Feb 26 '16 at 13:06
  • 1
    It's the same as when it is positional. With positional arguments, you can use `*args` which will not take *all* positional arguments; it will take only those that have not been accounted for. It is the same thing with `**kwargs`. `a` was already accounted for, but `b` wasn't so `kwargs` took it. – zondo Feb 26 '16 at 13:39