DEV Community

Cover image for Python Pro Tip: Mastering *args and **kwargs (Argument Packing Explained) ๐ŸŽ
Aaron Rose
Aaron Rose

Posted on

Python Pro Tip: Mastering *args and **kwargs (Argument Packing Explained) ๐ŸŽ

You've mastered unpacking, which splits an iterable into individual variables. Now, let's look at the opposite process: variable packing. Packing is about collecting multiple, independent values into a single variable, typically a tuple or a dictionary. This is a crucial concept, especially when building flexible functions.


Packing Positional Arguments with *args

The single asterisk (*) is a packing operator when used in a function definition. It allows a function to accept a variable number of positional arguments (arguments passed without a keyword) and collects them all into a single tuple. The conventional name for this parameter is args, short for "arguments."

Imagine you want a function that can calculate the sum of any number of values, without having to define a separate parameter for each one. This is a perfect job for *args.

def my_sum(*args):
    """Calculates the sum of any number of values."""
    return sum(args)

# You can call the function with any number of arguments
print(my_sum(1, 2, 3))
print(my_sum(10, 20, 30, 40, 50))
Enter fullscreen mode Exit fullscreen mode

Output:

6
150
Enter fullscreen mode Exit fullscreen mode

To see whatโ€™s happening under the hood, letโ€™s inspect the args variable itself in a new example. Itโ€™s a tuple containing all the positional arguments.

def inspect_args(*args):
    print(f"Packed tuple: {args}")
    print(f"Type: {type(args)}")

inspect_args(1, "hello", True)
Enter fullscreen mode Exit fullscreen mode

Output:

Packed tuple: (1, 'hello', True)
Type: <class 'tuple'>
Enter fullscreen mode Exit fullscreen mode

Packing Keyword Arguments with **kwargs

The double asterisk (**) is used to pack a variable number of keyword arguments (arguments passed in the key=value format) into a single dictionary. The conventional name is kwargs, short for "keyword arguments."

This is incredibly useful for functions that take an arbitrary set of configuration options or user details. Here's a real-world-inspired example for an API client function.

def configure_api(**kwargs):
    """Configures an API client with optional settings."""
    defaults = {'timeout': 5, 'retries': 3, 'api_key': 'default'}
    defaults.update(kwargs)

    print("--- API Configuration ---")
    for key, value in defaults.items():
        print(f"{key.replace('_', ' ').title()}: {value}")
    print("-------------------------")

configure_api(api_key='your_secret_key', retries=5)
Enter fullscreen mode Exit fullscreen mode

Output:

--- API Configuration ---
Timeout: 5
Retries: 5
Api Key: your_secret_key
-------------------------
Enter fullscreen mode Exit fullscreen mode

Using Both *args and **kwargs

You can even combine both *args and **kwargs in a single function definition. When you do, the order matters: positional arguments come first, followed by *args, and finally **kwargs. This is a strict rule in Python.

def flexible_function(required_arg, *args, **kwargs):
    print(f"Required Argument: {required_arg}")
    print(f"Positional Arguments (*args): {args}")
    print(f"Keyword Arguments (**kwargs): {kwargs}")

flexible_function("hello", 1, 2, 3, a=10, b=20)
Enter fullscreen mode Exit fullscreen mode

Output:

Required Argument: hello
Positional Arguments (*args): (1, 2, 3)
Keyword Arguments (**kwargs): {'a': 10, 'b': 20}
Enter fullscreen mode Exit fullscreen mode

Because args is a tuple and kwargs is a dictionary, you can use all the usual methods like len(args) or kwargs.get('key') to safely handle the values inside.


Conclusion: Why This Matters

Variable packing is a fundamental Python idiom that allows you to write functions that are more dynamic, flexible, and robust. It's the key to making your code DRY (Don't Repeat Yourself) by allowing a single function to handle a wide range of inputs without needing endless if/else statements or boilerplate code. In the real world, *args and **kwargs are widely used in frameworks like Django and FastAPI to create highly configurable functions and reusable components. Mastering this simple pattern is a crucial step toward writing truly professional, future-proof code.


Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.

Top comments (0)