Python
Programming
Code
*args
**kwargs

What do args and kwargs mean?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Python, *args and **kwargs let a function accept a variable number of arguments. They are useful when the exact number of inputs is not fixed ahead of time, especially in wrappers, decorators, forwarding functions, and extensible APIs.

What *args Means

*args collects extra positional arguments into a tuple.

python
1def show_args(*args):
2    print(args)
3
4
5show_args(1, 2, 3)

This prints:

text
(1, 2, 3)

The name args is only a convention. You could write *values or *items, but *args is the common style people expect to see.

The important part is the *, not the word args.

What **kwargs Means

**kwargs collects extra keyword arguments into a dictionary.

python
1def show_kwargs(**kwargs):
2    print(kwargs)
3
4
5show_kwargs(name="Mina", active=True)

This prints something like:

text
{'name': 'Mina', 'active': True}

Again, the name kwargs is conventional. The ** is what gives the parameter its behavior.

Using Both Together

A function can accept both kinds of variable arguments at the same time:

python
1def demo(*args, **kwargs):
2    print("args:", args)
3    print("kwargs:", kwargs)
4
5
6demo(10, 20, user="noa", admin=False)

This is common in wrapper functions because they can accept almost anything and forward it elsewhere.

Why They Are Useful

The classic use case is writing a wrapper or decorator without hardcoding the wrapped function’s full parameter list.

python
1from functools import wraps
2
3
4def traced(func):
5    @wraps(func)
6    def wrapper(*args, **kwargs):
7        print(f"calling {func.__name__}")
8        result = func(*args, **kwargs)
9        print(f"result={result}")
10        return result
11    return wrapper
12
13
14@traced
15def multiply(a, b):
16    return a * b
17
18
19print(multiply(3, 7))

Without *args and **kwargs, this kind of reusable wrapper would be much more awkward.

Definition Order Matters

Function parameter order in Python follows rules. In a definition, *args must come before **kwargs.

python
1def send_event(event_name, *args, retry=False, **kwargs):
2    return {
3        "event_name": event_name,
4        "args": args,
5        "retry": retry,
6        "kwargs": kwargs,
7    }
8
9
10print(send_event("login", 42, "web", retry=True, ip="10.0.0.8"))

That order matters because Python needs to know which inputs are positional, which are keyword-only, and which belong in the flexible collections.

Unpacking at the Call Site

The same syntax also works in reverse when calling a function.

* unpacks a sequence into positional arguments:

python
1def greet(name, lang):
2    print(name, lang)
3
4
5values = ("Ari", "en")
6greet(*values)

** unpacks a dictionary into keyword arguments:

python
1def greet(name, lang):
2    print(name, lang)
3
4
5options = {"name": "Noa", "lang": "fr"}
6greet(**options)

This is one reason the feature is so powerful. The same operators help both in function definitions and in function calls.

When Not to Use Them

Just because *args and **kwargs are flexible does not mean every function should use them.

If a function has a stable, well-known interface, explicit parameters are usually better:

python
def create_user(name: str, email: str, is_admin: bool = False):
    return {"name": name, "email": email, "is_admin": is_admin}

This is easier to read, easier to type-check, and easier for IDEs to help with.

So a good rule is:

  • use dynamic argument capture when flexibility is truly needed
  • use explicit parameters when the API is known and stable

Common Pitfalls

The most common pitfall is thinking args and kwargs are special names. They are not. The stars are what matter.

Another mistake is overusing *args and **kwargs for ordinary application functions where explicit parameters would be much clearer.

A third issue is forwarding **kwargs blindly to another function that does not accept all those keys. That can create surprising runtime errors.

Finally, beginners sometimes forget the data types involved: *args becomes a tuple and **kwargs becomes a dictionary.

Summary

  • '*args collects extra positional arguments into a tuple.'
  • '**kwargs collects extra keyword arguments into a dictionary.'
  • They are especially useful for wrappers, decorators, and forwarding functions.
  • The names args and kwargs are conventions; the stars are the real syntax.
  • Prefer explicit function signatures when the interface is stable and well known.

Course illustration
Course illustration

All Rights Reserved.