DEV Community

Adam Lombard
Adam Lombard

Posted on • Edited on

Python: What are *args and **kwargs?

We may encounter Python function definitions that look something like this:

def a_function(*args, **kwargs):
    ...
Enter fullscreen mode Exit fullscreen mode

The asterisks denote parameters able to receive variable-length arguments. (The args and kwargs names don't matter โ€” they're merely conventions, and stand for 'arguments' and 'keyword arguments' respectively. Any appropriate parameter names may be used.)

Say we need a function enabling users to share their hobbies, but we don't know in advance how many hobbies a given user will have:

def my_hobbies(*hobbies):
    print("My hobbies: " + ", ".join(hobbies))
Enter fullscreen mode Exit fullscreen mode

Our function now accepts one or more arguments:

>>> my_hobbies('reading', 'writing')
My hobbies: reading, writing

>>> my_hobbies('reading', 'writing', 'hiking', 'learning Python')
My hobbies: reading, writing, hiking, learning Python
Enter fullscreen mode Exit fullscreen mode

Conveniently, we can also call our function by passing it a tuple, using similar asterisk syntax:

>>> some_hobbies = ('reading', 'writing', 'hiking', 'learning Python')
>>> my_hobbies(*some_hobbies)
My hobbies: reading, writing, hiking, learning Python
Enter fullscreen mode Exit fullscreen mode

Now say we want a function enabling users to share their favorite things in various categories, but we don't know in advance how many categories a given user will select:

def my_faves(**favorites):
    print("My favorite things...")
    for category, fave in favorites.items():
        print(f"{category}: {fave}")
Enter fullscreen mode Exit fullscreen mode

Our function now accepts one or more keyword arguments:

>>> my_faves(Color='green', Fruit='persimmon')
My favorite things...
Color: green
Fruit: persimmon

>>> my_faves(Season='winter', Language='Python', Website='dev.to')
My favorite things...
Season: fall
Language: Python
Website: dev.to
Enter fullscreen mode Exit fullscreen mode

We can also call our function by passing it a dictionary, using similar double asterisk syntax:

>>> some_faves = {"Animal": "whale", "Summer Hobby": "hiking"}
>>> my_faves(**some_faves)
My favorite things...
Animal: whale
Summer Hobby: hiking
Enter fullscreen mode Exit fullscreen mode

A function may be defined with a mixture of formal parameters, variable-length parameters, and variable-length keyword parameters. When doing so, they must appear in the definition in the following order:

def a_function(arg, *args, **kwargs):
    ...
Enter fullscreen mode Exit fullscreen mode

More information can be found in the Python documentation.


Was this helpful? Did I save you some time?

๐Ÿซ– Buy Me A Tea! โ˜•๏ธ


Top comments (7)

Collapse
 
waylonwalker profile image
Waylon Walker • Edited

*args and **kwargs are so powerful. I have cut large sections of hard to maintain code completely out with them. I do find it hard to teach/learn/grasp. I just released a post trying to share them as well.

I think some of this comes from seeing really confusing implementations. I really like how you chose to use *hobbies and **favorites here. I think generalizing with *args and **kwargs only adds to the confusion, and for some reason that is what appears more often than not.

understanding python args and kwargs

Collapse
 
hasii2011 profile image
Humberto A Sanchez II

A nice simple concise explanation of args and kwargs

Collapse
 
adamlombard profile image
Adam Lombard

Thanks! ๐Ÿ™‚

Collapse
 
serg_syd profile image
Sergio • Edited

What is the difference if I just used list or dictionary as arguments?

def my_hobbies(hobbies_list):
print("My hobbies: " + ", ".join(hobbies_list))

Collapse
 
adamlombard profile image
Adam Lombard • Edited

In our simple example, there isn't much of a difference.

In a real-world example, the *args and *kwargs syntax give us more options in how we accept data into our function.

The decision is largely one between:
A) forcing the use of structured data, and...
B) not needing to know the structure in advance.

In your example, we must always pass in a list or dictionary, even if we are only passing in a single hobby. (This approach is not necessarily bad -- it may, in fact, be the right solution.) If, instead, we allow variable-length arguments -- by using the *args or *kwargs syntax -- then we do not need to structure the data in advance.

A more in-depth discussion related to your question can be found here.

Collapse
 
machanic16 profile image
Joel Tovar

Excellent explanation, thanks!

Collapse
 
adamlombard profile image
Adam Lombard

You're welcome! ๐Ÿ™‚