Understanding *args & **kwargs in Python

Sachin Pal
6 min readJul 25, 2022
*args and **kwargs in Python
Source: Author(GeekPython)

When we see the documentation of any function that contains *args and **kwargs, have you ever wondered — What are these strange parameters passed inside that function?

As an example:

function(params, *args, **kwargs)

As a beginner, you might get confused about how to use that function or what to pass as an argument in place of * args and ** kwargs when calling that function.

Well not to worry, in this tutorial we gonna discuss *args and **kwargs - What they mean and their uses in the function with examples that help you to understand better.

And we gonna see the glimpse of * and ** (Unpacking operators) used in the examples.

Introduction

The function in Python helps us to write code that is reused, to perform particular tasks in various operations.

Let’s define a function that prints character names:

Example: function that prints character names

def characters(name1, name2, name3):
print(name1, name2, name3)

characters("Iron Man", "Black Panther", "Captain America")

If we run the program, the output would be

Iron Man Black Panther Captain America

The function " characters " above takes 3 positional arguments "name1", "name2", "name3" and simply prints the names.

What if we pass more than the number of arguments that it takes

def characters(name1, name2, name3):
print(name1, name2, name3)

characters("Iron Man", "Black Panther", "Captain America", "Hulk")

What do you think the output would be, the output will be a TypeError

TypeError: characters() takes 3 positional arguments but 4 were given

The error was raised because the function won’t be able to handle the intensity of the Incredible Hulk, I wish I could say that but, the error was raised due to the extra argument passed inside the function that takes only 3 arguments

That is sad because we need to pass one more argument inside the function character to execute code without any error.

But this is not the best practice, suppose you are working on a project where you need to add multiple arguments dynamically when you are calling a particular function.

What to do in such cases? There’s a way to tackle such situations…

Usage of Python *args

*args is simply shortened for arguments. It is used as an argument when we are not sure how many arguments should we pass in the function.

The * asterisk before the args ensures that the argument has a variable length.

*args is a Non-keyword argument or a Positional argument.

By using *args, you are allowed to pass any number of arguments when calling a function.

Example: Using *args in function definition

def friends(*args):
print(args)

friends("Sachin", "Rishu", "Yashwant", "Abhishek")

Output

('Sachin', 'Rishu', 'Yashwant', 'Abhishek')

We got our output as Tuple because when we use *args the function will get the arguments as Tuple

If we check the type:

def friends(*args):
print(type(args))
print(args)

friends("Sachin", "Rishu", "Yashwant", "Abhishek")

Output

<class 'tuple'>
('Sachin', 'Rishu', 'Yashwant', 'Abhishek')

We can also use regular arguments with *args

Example: Using regular arguments and args in the function definition

def friends(greet, *args):
for friend in args:
print(f"{greet} to Python, {friend}")

greet = "Welcome"
friends(greet, "Sachin", "Rishu", "Yashwant", "Abhishek")

Output

Welcome to Python, Sachin
Welcome to Python, Rishu
Welcome to Python, Yashwant
Welcome to Python, Abhishek

Note: You can use any name, whatever it may be it could be your pet’s name, friend’s name even your girlfriend’s name instead of args but make sure you put * asterisk before that name.

Example: Using a different name instead of args

def dog(prefix, *german_shepherd):
for breed in german_shepherd:
print(f"The {prefix} is {breed}.")

prefix = "breed"
dog(prefix, "Labrador", "GSD", "Chihuahua")

Output

The breed is Labrador.
The breed is GSD.
The breed is Chihuahua.

There is an exception — When you pass regular argument and *args inside the function together as a parameter, never pass *args before regular argument.

Example: Using *args before regular argument inside the function

def heroes(*characters, country):
for character in characters:
print(f"{character} is from {country}.")

country = "USA"
heroes(country, "Iron Man", "Captain America", "Spiderman")

What do you think the output would be

TypeError: heroes() missing 1 required keyword-only argument: 'country'

The output will be a TypeError because we cannot pass *args before the regular argument.

If we modify the code and change the position of parameters passed inside the function then there will be no error

def heroes(country, *characters):
for character in characters:
print(f"{character} is from {country}.")

country = "USA"
heroes(country, "Iron Man", "Captain America", "Spiderman")

Output

Iron Man is from USA.
Captain America is from USA.
Spiderman is from USA.

The above code is executed without any error.

Usage of Python **kwargs

**kwargs is shortened for Keyword argument.

Now you are familiar with *args and know its implementation, **kwargs works similarly as *args.

But unlike *args, **kwargs takes keyword or named arguments.

In **kwargs, we use ** double asterisk that allows us to pass through keyword arguments.

Example: Using **kwargs in the function definition

def hello(**kwargs):
print(type(kwargs))
for key, value in kwargs.items():
print(f"{key} is {value}.")

hello(One = "Red", two = "Green", three = "Blue")

Output

<class 'dict'>
One is Red.
two is Green.
three is Blue.

The type of **kwargs is Dictionary i.e., the arguments accepted as key-value.

Example: Using regular argument and **kwargs together inside a function definition

def hello(write, **kwargs):
print(write)
for key, value in kwargs.items():
print(f"{key} is {value}.")
write = "RGB stands for:"
hello(write, One = "Red", two = "Green", three = "Blue")

Output

RGB stands for:
One is Red.
two is Green.
three is Blue.

Just like *args, you can choose any name instead of **kwargs

Example: Using a different name instead of kwargs

def hello(write, **color):
print(write)
for key, value in color.items():
print(f"{key} is {value}.")
write = "RGB stand for:"
hello(write, One = "Red", two = "Green", three = "Blue")

Output

RGB stand for:
One is Red.
two is Green.
three is Blue.

Note: We cannot pass **kwargs before *args in the function definition otherwise, we'll get a SyntaxError.

The convention should be — function(params, *args, **kwargs)

Example

We can use all three types of arguments inside the function definition and in this example, you’ll see the use of the unpacking operator* and **.

def friends(greet, *args, **kwargs):
for names in args:
print(f"{greet} to the Programming zone {names}")
print("\nI am Veronica and I would like to announce your roles:")
for key, value in kwargs.items():
print(f"{key} is a {value}")

greet = "Welcome"
names = ["Sachin", "Rishu", "Yashwant", "Abhishek"]
roles = {"Sachin":"Chief Instructor", "Rishu":"Engineer",
"Yashwant":"Lab Technician", "Abhishek":"Marketing Manager"}

friends(greet, *names, **roles)

The output would be

Welcome to the Programming zone Sachin
Welcome to the Programming zone Rishu
Welcome to the Programming zone Yashwant
Welcome to the Programming zone Abhishek

I am Veronica and I would like to announce your roles:
Sachin is a Chief Instructor
Rishu is a Engineer
Yashwant is a Lab Technician
Abhishek is a Marketing Manager

In the above code snippet, you can notice that I created variables named names and roles.

But when I call them in a function, I used * before the names variable and ** before the roles variable.

These are the Unpacking operators.

Unpacking Operator

These operators come quite in handy as you saw above.

* single asterisk is used to unpack iterable and ** double asterisk is used to unpack a dictionary.

The * iterable unpacking operator and ** dictionary unpacking operators to allow unpacking in more positions, an arbitrary number of times, and in additional circumstances. Specifically, in function calls, in comprehensions and generator expressions, and in displays. Source

To know more, click here

Conclusion

So far you will now be able to implement the fundamentals of *args and **kwargs inside the functions.

These might come in handy when you are working on projects where data comes dynamically in a function and you don’t know how many arguments to be passed in that function. This makes your project scalable.

That’s all for now

Keep Coding✌✌.

Originally published at https://geekpython.in.

--

--

Sachin Pal

I am a self-taught Python developer who loves to write on Python Programming and quite obsessed with Machine Learning.