Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Misunderstanding kwargs?
#1
I went ahead and checked out some examples in other threads. I feel like I am still misunderstanding how exactly the interpreter handles **kwargs. I have the basics of *args understood and I feel pretty confident about how I think **kwargs is working. I just want to make sure its concrete.

So in my code example here, I need to understand why we use **kwargs and not just simply use kwargs? If I am understanding this correctly, the "*" or "wildcard" allows us to have a placeholder that can be replaced by any string or specified value (with some limitations I assume). This is confusing me because while learning the basics I have created my example and it doesn't exactly have the need for this type of **kwarg positional argument or it atleast as I understand. I don't exactly want to continue fiddling with it until I understand it more, it just seems to become more confusing when I do that, so I usually go back and read more. I understand that the wildcard is suppose to handle an unspecified number of arguments, that way you can have lists and dictionaries of an unknown size be sent through a function that can be called on with however many arguments you put.

So I guess, my question is this. Is this correct usage for **kwargs. Does anyone have a better way of explaining and understanding it's syntax and implementation. Thank you all for keeping this place going and providing an awesome community. I will continue reading while I wait for some responses.

kwargs = {"kwarg1": 1, "kwarg2": 2, "kwarg3": 3}
def some_func(*args, **kwargs):
    print("*Args:", *args)

some_func("AnArg1", "AnArg2", "AnArg3", kwargs)
    
Quick Edit: I have been fiddling more and these are the examples I have come up with and read up on.

def greet_me(**kwargs):
    for key, value in kwargs.items():
        print("{0} = {1}".format(key, value))


def test_args_kwargs(arg1, arg2, arg3):
    print("arg1:", arg1)
    print("arg2:", arg2)
    print("arg3:", arg3)

args = ("two", 3, 5)
test_args_kwargs(*args)

kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
test_args_kwargs(**kwargs)

kwargs = {"kwarg1": 1, "kwarg2": 2, "kwarg3": 3}
def some_func(*args, **kwargs):
    print("*Args:", *args)
 
some_func("AnArg1", "AnArg2", "AnArg3", kwargs)
The output is this:
Quote:arg1: two
arg2: 3
arg3: 5
arg1: 5
arg2: two
arg3: 3
*Args: AnArg1 AnArg2 AnArg3 {'kwarg1': 1, 'kwarg2': 2, 'kwarg3': 3}

Where the output spits out the last string of args and kwargs. Id like to separate them on two lines. I also want to make sure I am properly using **kwargs. If there is any advice on Do's and Don'ts I will definetely take it.

Trying to achieve this output:
Quote:arg1: two
arg2: 3
arg3: 5
arg1: 5
arg2: two
arg3: 3
*Args: AnArg1 AnArg2 AnArg3
**KWArgsg: {'kwarg1': 1, 'kwarg2': 2, 'kwarg3': 3}
Reply
#2
def test(*args, **kvargs):
    print(type(args), args, type(kvargs), kvargs)

test('this', 'is', a='a', test='test')
test(*('this', 'is'), **{'a':'a', 'test':'test'})
Output:
<class 'tuple'> ('this', 'is') <class 'dict'> {'a': 'a', 'test': 'test'} <class 'tuple'> ('this', 'is') <class 'dict'> {'a': 'a', 'test': 'test'}
So args is a tuple and kvargs is a dictionary.
*(1, 2, 3) extracts the values from the tuple and provides them as separate items instead of a collection. This is called "unpacking". You can also unpack a dictionary though what is returned is less obvious.

You don't have to understand how kvargs works to use it. Even though kvargs is a dictionary you should not be treating it as a dictionary. To extract values from *args and **kvargs you specify arguments for your function:
def leftovers(*args, **kvargs):
    print(args, kvargs)

def filter(a, *args, b='thing', **kvargs):
    leftovers(*args, **kvargs)

filter(1, 2, b=3, c=4)
Output:
(2,) {'c': 4}
The function "filter" consumes the first position argument and the 'b' keyword argument. The remaining arguments can be passed on to the "leftovers" function. This is so much simpler than:
def leftovers(*args, **kvargs):
    print(args, kvargs)

def filter(*args, **kvargs):
    a = args[0]
    b = kvargs['b']
    del kvargs['b']
    leftovers(args[1:], **kvargs)

filter(1, 2, b=3, c=4)
Reply
#3
Thank you for your examples, I am going to fiddle around with it some more but I think this has helped a lot. I will be sure to add some reputation for your help, thanks again Deanhystad.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How do I instantiate a class with **kwargs? palladium 6 7,310 Feb-16-2023, 06:10 PM
Last Post: deanhystad
  kwargs question Jeff_t 8 2,954 Feb-16-2022, 04:33 PM
Last Post: Jeff_t
  **kwargs question DPaul 10 4,308 Apr-01-2020, 07:52 AM
Last Post: buran
  Unpacking dictionary from .xlsx as Kwargs etjkai 5 2,848 Dec-27-2019, 05:31 PM
Last Post: etjkai
  opts vs kwargs Skaperen 4 2,450 Nov-30-2019, 04:57 AM
Last Post: Skaperen
  misunderstanding of format in print function Harvey 2 2,175 Oct-29-2019, 12:44 PM
Last Post: buran
  Simple list comprehension misunderstanding Mark17 3 2,562 Oct-10-2019, 07:00 PM
Last Post: buran
  Bug or my misunderstanding? MrSteveVee 2 3,466 Jan-04-2018, 10:58 PM
Last Post: MrSteveVee
  Misunderstanding with the “if” statement and “not equal” scriptoghost 6 4,422 Jun-23-2017, 09:43 AM
Last Post: DeaD_EyE
  create dictionary from **kwargs that include tuple bluefrog 2 4,870 Oct-26-2016, 10:24 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020