In Python, functions are one of the most essential parts of programming. They help you organize code, reduce repetition, and make your projects more readable. However, sometimes you may not know in advance how many arguments a function should accept. That’s where Python arbitrary arguments come in handy — specifically *args
and **kwargs
. These two features allow you to create flexible functions that can handle a dynamic number of inputs.
What Are Arbitrary Arguments in Python?
Arbitrary arguments in Python refer to the use of special symbols *
and **
that allow a function to accept an undefined number of parameters. The symbol *
is used for non-keyword arguments (positional arguments), while **
is used for keyword arguments (dictionary-like arguments).
- *args – collects extra positional arguments into a tuple.
- **kwargs – collects extra keyword arguments into a dictionary.
This flexibility allows you to create functions that adapt to various input cases without changing the function definition each time.
Using *args in Python
The *args
parameter lets your function receive any number of positional arguments. These arguments are passed as a tuple. You can loop through them or manipulate them just like any other tuple in Python.
Example of *args
def sum_numbers(*args): total = 0 for number in args: total += number return total print(sum_numbers(1, 2, 3)) # Output: 6 print(sum_numbers(10, 20, 30, 40)) # Output: 100
In this example, the function sum_numbers()
can handle any number of numeric inputs. When you call sum_numbers(1, 2, 3)
, the *args
collects (1, 2, 3)
into a tuple and sums them up.
Advantages of Using *args
- Allows function flexibility with multiple arguments.
- Useful when you don’t know how many inputs will be passed.
- Improves code reusability and modularity.
Using **kwargs in Python
While *args
handles positional arguments, **kwargs
is used to handle keyword arguments — meaning arguments passed with names. These arguments are stored in a dictionary where the keys are the argument names and the values are their respective values.
Example of **kwargs
def print_person_info(**kwargs): for key, value in kwargs.items(): print(f"{key}: {value}") print_person_info(name="Alice", age=25, city="New York")
Output:
name: Alice age: 25 city: New York
In this case, the function print_person_info()
can handle any number of keyword arguments. It stores them in a dictionary and prints each key-value pair.
Advantages of Using **kwargs
- Provides flexibility for named arguments.
- Useful for passing configuration settings or dynamic attributes.
- Allows functions to accept optional parameters without changing the definition.
Combining *args and **kwargs
You can use both *args
and **kwargs
in the same function definition to handle both positional and keyword arguments simultaneously. The order of parameters in the function definition should always be:
def example_function(positional, *args, keyword_only, **kwargs): pass
Here’s a practical example:
def display_details(*args, **kwargs): print("Positional arguments (args):", args) print("Keyword arguments (kwargs):", kwargs) display_details(1, 2, 3, name="Bob", job="Developer")
Output:
Positional arguments (args): (1, 2, 3) Keyword arguments (kwargs): {'name': 'Bob', 'job': 'Developer'}
This combination makes your function extremely flexible and capable of handling different kinds of arguments at once.
Practical Example: Dynamic Calculator
Let’s create a more real-world example to demonstrate the use of *args
and **kwargs
together.
def calculator(*args, **kwargs): operation = kwargs.get('operation', 'add') result = 0 if operation == 'add': result = sum(args) elif operation == 'multiply': result = 1 for num in args: result *= num elif operation == 'average': result = sum(args) / len(args) if args else 0 else: return "Invalid operation" return result print(calculator(1, 2, 3, 4, operation='add')) # Output: 10 print(calculator(1, 2, 3, 4, operation='multiply')) # Output: 24 print(calculator(10, 20, 30, operation='average')) # Output: 20.0
Here, *args
collects all the numeric values, and **kwargs
determines which operation to perform. This structure allows you to extend functionality easily without modifying the base code.
Key Differences Between *args and **kwargs
Feature | *args | **kwargs |
---|---|---|
Type | Tuple | Dictionary |
Handles | Positional arguments | Keyword arguments |
Use case | Unknown number of positional parameters | Unknown number of keyword parameters |
Tips for Using *args and **kwargs Effectively
- Always use descriptive names inside the function when processing
*args
and**kwargs
. - Don’t overuse them — only use them when truly necessary.
- Combine them with default parameters for more flexibility.
- Maintain readability by documenting the expected argument types in comments or docstrings.
Conclusion
The use of *args and **kwargs in Python makes your code flexible, dynamic, and scalable. Whether you’re building simple utilities or complex applications, understanding how to handle arbitrary arguments allows you to design smarter and cleaner functions. They are powerful tools that every Python developer should master to write efficient, reusable, and adaptable code.
Now that you understand how *args
and **kwargs
work, try implementing them in your own projects. You’ll see how much simpler and more dynamic your Python functions can become!