Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the key 'kwargs' appear when using **kwargs?

Why does {'kwargs':{'1':'a', '2':'b'}} appear when I run test_func()? I would have expected just this to print: {'1':'a', '2':'b'}.

Code:

class MyClass:
    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def test_func(self):
        print(self.kwargs)

test_kwargs = {'1':'a', '2':'b'}
my_class = MyClass(kwargs=test_kwargs)
my_class.test_func()

Ouput:

{'kwargs': {'1': 'a', '2': 'b'}}
like image 288
narnia649 Avatar asked Dec 31 '22 13:12

narnia649


2 Answers

It's because you initialize the instance by passing 1 keyword argument named kwargs with the dictionary as value.

If you want to see the dictionary as kwargs, you need to call in using my_class = MyClass(**test_kwargs)

like image 101
DevLounge Avatar answered Jan 02 '23 03:01

DevLounge


It's because **kwargs automagically collects the remaining (unused) named arguments and puts them in a dictionary for you, much the same as *args collects the unused unnamed (positional) arguments into a tuple(a).

It's meant to handle things like:

my_class = MyClass(a=1, b=2)

which is possibly what you were trying to do.

The way you've done it in the question will result in a dictionary with the key kwargs referencing the dictionary because it will create a single dictionary keyed on the argument name kwargs - that is exactly what you see.


(a) You can see this behaviour in the following transcript:

Python 3.9.0 (default, Oct 12 2020, 02:44:01)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def fn(one, two, *args, **kwargs):
...     print(one)
...     print(two)
...     print(args)
...     print(kwargs)
...
>>> fn(1, 2, 3, 4, 5, six=6, seven=7)
1
2
(3, 4, 5)
{'six': 6, 'seven': 7}

Keep in mind args and kwargs are conventions, not rules. You can use different names, it's the * and ** that matter.

like image 44
paxdiablo Avatar answered Jan 02 '23 04:01

paxdiablo