*args and **kwargs in Python Explained with Examples
When writing functions in Python, you may not always know how many arguments will be passed. Sometimes you need flexible function signatures to handle both positional and keyword arguments without rewriting your code repeatedly.
That’s where *args
and **kwargs
come in.
In this detailed guide, we’ll explore:
- What
*args
and**kwargs
mean. - How they work in Python.
- Practical code examples.
- Their role in object-oriented programming.
- Common interview questions and mistakes.
By the end of this post, you’ll fully understand how to use *args and **kwargs in Python
effectively and naturally in your projects.
What are *args
and **kwargs
?
*args
allows a function to accept a variable number of positional arguments.**kwargs
allows a function to accept a variable number of keyword (named) arguments.
They are not special keywords — you could technically use *numbers
or **data
— but *args
and **kwargs
are standard naming conventions widely adopted in Python codebases.
Understanding *args
in Python
*args
lets you pass multiple positional arguments into a function without explicitly defining them.
Example 1: Summing Numbers
def add_numbers(*args):
return sum(args)
print(add_numbers(2, 3)) # 5
print(add_numbers(1, 2, 3, 4, 5)) # 15
Here:
args
is collected into a tuple:(2, 3)
or(1, 2, 3, 4, 5)
.- You can pass any number of arguments without changing the function definition.
Example 2: Printing Arguments
def show_args(*args):
for arg in args:
print(arg)
show_args("Python", "Java", "C++")
Output:
Python
Java
C++
This shows that *args
can handle multiple items of any data type.
Understanding **kwargs
in Python
**kwargs
collects all extra keyword arguments into a dictionary. This makes it useful when you don’t know in advance which named arguments will be passed.
Example 1: Printing Key-Value Pairs
def print_details(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_details(name="Alice", age=25, city="New York")
Output:
name: Alice
age: 25
city: New York
Here:
kwargs
is a dictionary:{'name': 'Alice', 'age': 25, 'city': 'New York'}
.
Example 2: Default Behavior with Flexibility
def greet(**kwargs):
if "name" in kwargs:
print(f"Hello, {kwargs['name']}!")
else:
print("Hello, Guest!")
greet(name="John") # Hello, John!
greet() # Hello, Guest!
Using *args
and **kwargs
Together
You can use both in the same function to handle maximum flexibility.
def demo_function(a, *args, **kwargs):
print("a:", a)
print("args:", args)
print("kwargs:", kwargs)
demo_function(1, 2, 3, x=10, y=20)
Output:
a: 1
args: (2, 3)
kwargs: {'x': 10, 'y': 20}
a
→ mandatory argumentargs
→ tuple of extra positional argumentskwargs
→ dictionary of extra keyword arguments
Order of Arguments in Python Functions
When defining functions, the correct order of arguments is:
- Normal (required) arguments
*args
- Default arguments
**kwargs
Example:
def sample_func(a, *args, b=5, **kwargs):
print(a, args, b, kwargs)
sample_func(10, 20, 30, b=50, x=100, y=200)
Output:
10 (20, 30) 50 {'x': 100, 'y': 200}
Real-World Use Cases of *args
and **kwargs
1. Flexible Mathematical Functions
def multiply(*args):
result = 1
for num in args:
result *= num
return result
print(multiply(2, 3, 4)) # 24
2. Configurable Functions
def configure_app(**kwargs):
for setting, value in kwargs.items():
print(f"{setting} set to {value}")
configure_app(debug=True, log_level="INFO", retries=3)
3. Extending Parent Classes in OOP
class Animal:
def __init__(self, **kwargs):
self.name = kwargs.get("name", "Unknown")
class Dog(Animal):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.breed = kwargs.get("breed", "Mixed")
dog = Dog(name="Buddy", breed="Golden Retriever")
print(dog.name, dog.breed)
Benefits of Using *args
and **kwargs
- Flexibility: Handle variable-length arguments easily.
- Reusability: Write generic functions usable in multiple contexts.
- Cleaner Code: Avoids rewriting multiple overloaded functions.
- Scalability: Useful in libraries and frameworks where users may pass many configurations.
- Supports OOP: Makes constructors and method overrides more versatile.
Common Mistakes with *args
and **kwargs
- Mixing up the order of arguments.
- Forgetting that
args
is a tuple andkwargs
is a dictionary. - Overusing them when explicit arguments would make the function clearer.
- Not providing defaults when using
kwargs.get()
.
Advanced Tip: Argument Unpacking
You can also use *
and **
to unpack lists or dictionaries when calling functions.
def display(a, b, c):
print(a, b, c)
nums = [1, 2, 3]
display(*nums) # 1 2 3
details = {"a": 10, "b": 20, "c": 30}
display(**details) # 10 20 30
FAQs
Q1: What’s the difference between *args
and **kwargs
?
A: *args
collects positional arguments into a tuple, while **kwargs
collects keyword arguments into a dictionary.
Q2: Can I rename args
and kwargs
to something else?
A: Yes, you can use *numbers
or **options
, but the convention is *args
and **kwargs
.
Q3: Are *args
and **kwargs
used in Python libraries?
A: Yes, many libraries (like Django, Flask, NumPy) use them to allow flexible configurations and extensibility.
Conclusion
Understanding *args and **kwargs in Python
is essential for writing flexible, clean, and scalable code. With *args
, you can handle variable positional arguments, while **kwargs
gives you the power to manage flexible keyword arguments.
From simple arithmetic functions to complex class hierarchies, these tools make your Python programs more robust and adaptable.
As you practice, you’ll find that using them not only makes your code more elegant but also prepares you for coding interviews and real-world projects.