Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

*args and **kwargs

Can someone please explain to me what these two do. I am super confused

2 Answers

Think of them as special variables that python created.

The *args allows your function to have the flexibility to take as many parameters your function might need. For example, if you have a class called “add” you want to take as many arguments the user provides to calculate a sum. The problem is you may not know how many arguments the user provided, so you can’t hard code the arguments into the function.

class Add:
    def __init__ (x, y):
        print x + y

This class could only take two arguments

class AddMultiple:
    def __init__ (*args):
        for x in args:
            total += x
        print total

This class could take as many arguments the user passes into AddMultiple and add them together.

The **kwargs does the same thing but puts those arguments into the for of key value pairs. So python is looking for an input by the user of “key=value” for example “name = John”

Hope this clears things up! Always good to ask questions to understand the fundamentals instead of just copying code :)

[MOD: added ```python formating -cf]

Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Good answer. I would add that it is the single asterisk * and the double asterisk ** that have the meaning and the "args" and "kwargs" are only a convention in the same way "self" and "cls" are used for method parameters.

Alternatively, think of * as "tuple packing" and ** as "dictionary packing". Any positional arguments not put into existing parameters will be packed in the tuple "args" (or whatever name gets used). Any keyword/value pairs not put into existing keyword arguments will be packed in to the dictionary "kwargs" (or whatever name is used).

>>> def packing(pos1, pos2, kw1=None, kw2=None, *args, **kwargs):
...     print(f"pos1:{pos1}, pos2:{pos2}, kw1:{kw1}, kw2:{kw2}")
...     print(f"type args:{type(args)}, args:{args}")
...     print(f"type kwargs:{type(kwargs)}, kwargs:{kwargs}")
... 
>>> packing("p1", "p2", 101, 102, "a", "b", kw3=203, kw4=204)
pos1:p1, pos2:p2, kw1:101, kw2:102
type args:<class 'tuple'>, args:('a', 'b')
type kwargs:<class 'dict'>, kwargs:{'kw3': 203, 'kw4': 204}

>>> def packing(pos1, pos2, kw1=None, kw2=None, *foo, **kwbar):
...     print(f"pos1:{pos1}, pos2:{pos2}, kw1:{kw1}, kw2:{kw2}")
...     print(f"type foo:{type(foo)}, foo:{foo}")
...     print(f"type kwbar:{type(kwbar)}, kwbar:{kwbar}")
... 
>>> packing("p1", "p2", 101, 102, "a", "b", kw3=203, kw4=204)
pos1:p1, pos2:p2, kw1:101, kw2:102
type foo:<class 'tuple'>, foo:('a', 'b')
type kwbar:<class 'dict'>, kwbar:{'kw3': 203, 'kw4': 204}

Thank you this helped clear my misunderstanding