Python *args and **kwargs

Probably one of the most misunderstood (or mysterious) terms in Python are the “args” and “kwargs”, prefixed with a single and double star (*) character respectively, but definitely one of the best features of Python once you understand how it works.

If you have not seen this before, here’s a sample code that contains both of them:

def my_super_function(*args, **kwargs):
    pass

You’ll also see these two inside class methods.

So what are those, you might ask?

*args

Args is short for “arguments”, and in this context refers to “positional arguments“.

To better understand the “positional” part of it, we’ll have to look at a normal or typical function definition.

def compute_net_salary(gross_salary, deductions):
    return gross_salary - deductions

That simple function takes in two (2) parameters namely “gross_salary” and “deductions” and returns the difference between those values. The 1st positional argument is “gross_salary” and the 2nd positional argument is “deductions”.

Here’s an example of how this function is used (you pass the gross salary and deductions amount and it returns the computed net salary:

case_a = compute_net_salary(35000, 2000)
print("Net Salary A: ", case_a)

If you executed that code, it will result in this:

Net Salary A: 33000

Nothing new here, in fact, that’s what you’d expect the output to be, right?

Well, what if someone or some application supplied the values in the wrong order or position?

case_b = compute_net_salary(2000, 35000)
print("Net Salary B: ", case_b)

So now, the gross salary was assigned to the deductions argument, and the deductions to the gross salary argument.

This would result in:

Net Salary B: -33000

Woh, woh, woh…. there would be a lot of visitors in the accounting department if this happens, right? 🙂

So, that’s why it’s called “positional” arguments — because their value or context is based on where they are positioned, and incorrectly passing values could be catastrophic as you’ve seen in our very simple scenario.

Positional arguments are also “required”, so if you omit one, it won’t run. For example, let’s not supply the deductions:

case_c = compute_net_salary(35000)

This will raise an exception like this:

As you can see, it won’t allow you to proceed if you forgot to pass a positional argument.

Okay, now let’s go to the other arg….

**kwargs

The “kw” stands for “keyword” which makes kwargs equal to keyword arguments.

The way to look at this is, keyword arguments are optional (because they have default values) and unlike args, the positions are not restricted to how they were defined.
As with the args, let’s also take a look at a typical function that uses keyword arguments.

Let’s take for example a function that enrolls an employee to the payroll system, and this function requires name and optional arguments “status” and “country” — which is also known as keyword arguments:

def enroll_employee(name, status='single', country='Philippines'):
    print(f"Enrolling {name} as {status} and from {country}")

Notice how the 2 keyword arguments have default values? That’s how you know they’re keyword arguments.

Okay, so let’s call this function in various different ways then see the results.

Cool! Focusing on the keyword arguments only, we don’t even need to provide both of them. We can simply pass one, and they don’t need to match the function signature.

Wait… you might be thinking “those aren’t *args and **kwargs, are you kidding me????”

Well, like I said, in order to understand *args and **kwargs that we’d have to look at their usual counterpart.

And now that you’ve seen those, let’s move to the actual *args and **kwargs 🙂

Let’s add an actual code in our first function and let’s just print the value of *args:

def my_super_function(*args, **kwargs):
    print(args)


my_super_function('cat', 123, 'dog')

So we called the function with 3 unique positional arguments and of different data types. Here’s what we get when we run this code:

CoffeeWithDennis> python main.py

('cat', 123, 'dog')

Wow! We got all 3 of them!
But let’s do more, cause this doesn’t look impressive at all…

Now that one looks useful 🙂

But where would you use something like this? Not having a unique name for parameters doesn’t make sense…

Okay, I’ll give you one use case and I’m sure you can come up with more.

Let’s say you have a list of names and you want to make sure they are all in proper case before saving them, how would we do it using this *args thing?

Still not cool enough for you? 🙂 Get some coffee cause you’re just probably tired 🙂

Now let’s go to **kwargs…

If you’re familiar with CSS, here’s an example that would be totally relatable to you (using **kwargs):

See? Those 2 are super cool and has tons of possibilities for great use!

I hope you learned something new today and that this inspires you to try them as well. 🙂

Leave a Comment