*args: Non-Keyword Variable-Length Arguments
- Purpose: Allows a function to accept any number of positional arguments.
- Syntax: A single asterisk (
*) followed by a variable name (commonlyargs). - Behavior: All additional positional arguments passed to the function are collected into a tuple.
Example:
def print_numbers(*args):
for number in args:
print(number)
# Call the function with multiple arguments
print_numbers(1, 2, 3, 4, 5)
Output:
1
2
3
4
5
**kwargs: Keyword Variable-Length Arguments
- Purpose: Allows a function to accept any number of keyword arguments.
- Syntax: Two asterisks (
**) followed by a variable name (commonlykwargs). - Behavior: All additional keyword arguments passed to the function are collected into a dictionary.
Example:
def print_key_values(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
# Call the function with multiple keyword arguments
print_key_values(name="Alice", age=30, location="Wonderland")
Output:
name: Alice
age: 30
location: Wonderland
Using *args and **kwargs Together
You can use both *args and **kwargs in the same function. However, *args must appear before **kwargs in the function definition.
Example:
def mixed_arguments(arg1, *args, **kwargs):
print(f"Fixed argument: {arg1}")
print(f"Variable arguments (tuple): {args}")
print(f"Keyword arguments (dict): {kwargs}")
# Call the function
mixed_arguments("Fixed", 1, 2, 3, name="Alice", age=30)
Output:
Fixed argument: Fixed
Variable arguments (tuple): (1, 2, 3)
Keyword arguments (dict): {'name': 'Alice', 'age': 30}
Key Points
- Flexibility:
*argsand**kwargsmake functions flexible, accommodating varying numbers and types of arguments. - Default Names: The names
argsandkwargsare conventions but can be changed (e.g.,*variables,**options). - Order Matters:
- Positional arguments first.
- Then
*args. - Followed by keyword-only arguments or defaults.
- Finally,
**kwargs.
Example Order:
def example(positional, *args, keyword_only=None, **kwargs):
pass
def display_args(*args, **kwargs):
# Displaying all positional arguments (args)
print("Positional arguments (args):")
for arg in args:
print(arg)
# Displaying all keyword arguments (kwargs)
print("\nKeyword arguments (kwargs):")
for key, value in kwargs.items():
print(f"{key}: {value}")
# Test the function with args and kwargs
display_args(1, 2, 3, name="Alice", age=25, city="New York")
Interview angle
- “What do
*argsand**kwargsdo?” - collect extra positional arguments into a tuple and extra keyword arguments into a dict. At the call site the same syntax unpacks a sequence or mapping into arguments. - “What are
/and*in a signature?” -/marks the end of positional-only parameters,*marks the start of keyword-only ones. Keyword-only is the useful one for readable APIs: it forces callers to name boolean flags rather than passing a bareTrue. - “Why is a mutable default dangerous?” - defaults are evaluated once at definition, so a
[]default is shared across every call. UseNoneand create inside. See tricky_questions/01_mutable_default_arguments.md.