What are *args ?
*args allows a function to accept any number of positional arguments.
It gathers extra positional arguments into a tuple.
def function_name(*args):
# args is a tuple
What are **kwargs ?
**kwargs allows a function to accept any number of keyword arguments.
It gathers extra keyword arguments into a dictionary.
def function_name(**kwargs):
# kwargs is a dictionary
Why Use *args and **kwargs?
Flexibility: Handle an unknown number of arguments dynamically.
Code Reusability: Write functions that work with varied input.
Convenience: Simplify passing data from one function to another.
How to Use *args
*args collects extra positional arguments passed to the function.
It is useful when you want to allow a function to accept any number of positional arguments.
When you use *args in a function definition, it captures all extra positional arguments into a tuple.
Example 1: Summing Number
def add_numbers(*args):
return sum(args)
print(add_numbers(1, 2, 3)) # Output: 6
print(add_numbers(10, 20, 30, 40)) # Output: 100
Here, *args captures all positional arguments into a tuple: (1, 2, 3).
Example 2: Flexible Greeting
def greet(*names):
for name in names:
print(f"Hello, {name}!")
greet("Alice", "Bob", "Charlie")
Hello, Alice!
Hello, Bob!
Hello, Charlie!
How to Use **kwargs
**kwargs collects extra keyword arguments passed to the function.
Example 1: Flexible Configuration
def print_config(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_config(name="Alice", age=25, job="Engineer")
Output:
name: Alice
age: 25
job: Engineer
Here, **kwargs captures arguments into a dictionary: {'name': 'Alice', 'age': 25, 'job': 'Engineer'}.
Example 2: API-like Behavior
def api_request(endpoint, **params):
print(f"Endpoint: {endpoint}")
print(f"Parameters: {params}")
api_request("users", id=123, active=True, role="admin")
Output:
Endpoint: users
Parameters: {'id': 123, 'active': True, 'role': 'admin'}
Combining *args and **kwargs
Example: Combining *args and **kwargs
def combined_example(*args, **kwargs):
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
combined_example(1, 2, 3, name="John", age=30, location="USA")
Output:
Positional arguments: (1, 2, 3)
Keyword arguments: {'name': 'John', 'age': 30, 'location': 'USA'}
You can use both *args and **kwargs together to handle any combination of arguments.
Example: Versatile Function
def versatile_function(*args, **kwargs):
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
versatile_function(1, 2, 3, name="Alice", age=25)
Output:
Positional arguments: (1, 2, 3)
Keyword arguments: {'name': 'Alice', 'age': 25}
Real-Life Analogies
Think of *args and **kwargs as tools that help you handle different scenarios:
Dinner Party (args): Guests bring their own dishes. You don’t know how many people will show up, but you handle them dynamically.
Restaurant Orders (kwargs): Each order is specified by name (e.g., “Pizza: Large, Toppings: Pepperoni”).
You don’t know which specific orders will come in advance.
Advanced Use-Cases of args and kwargs
1. Passing Arguments to Another Function
You can pass *args and **kwargs to other functions dynamically.
def outer_function(*args, **kwargs):
print("Outer Function:")
print("Args:", args)
print("Kwargs:", kwargs)
inner_function(*args, **kwargs)
def inner_function(a, b, name=None):
print("\nInner Function:")
print(f"a: {a}, b: {b}, name: {name}")
outer_function(10, 20, name="Alice")
Output:
Outer Function:
Args: (10, 20)
Kwargs: {'name': 'Alice'}
Inner Function:
a: 10, b: 20, name: Alice
2. Using Default and Extra Arguments
2. Using Default and Extra Arguments
You can mix regular arguments with *args and **kwargs.
def example_function(x, y, *args, z=0, **kwargs):
print(f"x: {x}, y: {y}, z: {z}")
print("Additional positional arguments:", args)
print("Additional keyword arguments:", kwargs)
example_function(1, 2, 3, 4, z=5, name="Alice", age=30)
Output:
x: 1, y: 2, z: 5
Additional positional arguments: (3, 4)
Additional keyword arguments: {'name': 'Alice', 'age': 30}
Real-Life Applications
1. Logging Function
Capture all arguments passed to a function for logging purposes.
def log_function_call(*args, **kwargs):
print("Function called with:")
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
log_function_call(10, 20, debug=True, user="Admin")
Decorators
*args and **kwargs are commonly used in Python decorators to handle arguments dynamically.
def decorator(func):
def wrapper(*args, **kwargs):
print("Before the function call")
result = func(*args, **kwargs)
print("After the function call")
return result
return wrapper
@decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Output:
Before the function call
Hello, Alice!
After the function call
API Requests Dynamic APIs may accept varying parameters, which can be handled with **kwargs.
def dynamic_api_call(endpoint, **params):
query = "&".join(f"{k}={v}" for k, v in params.items())
url = f"https://example.com/{endpoint}?{query}"
print(f"Requesting URL: {url}")
dynamic_api_call("search", q="Python", limit=10, sort="asc")
Output:
Requesting URL: https://example.com/search?q=Python&limit=10&sort=asc
Best Practices
Order of Arguments: Always follow this order:
Regular arguments
*args
Default arguments
**kwargs
def function(a, *args, b=0, **kwargs):
pass
Readability: Avoid overusing *args and **kwargs when explicit arguments make the code clearer.
Documentation: Document the purpose of extra arguments when using *args and **kwargs.
Key Takeaways
*args captures variable-length positional arguments as a tuple.
**kwargs captures variable-length keyword arguments as a dictionary.
They allow flexibility in designing reusable, dynamic, and modular functions.
Use cases include APIs, decorators, and dynamic argument handling.