Variable-Length Arguments (*args and **kwargs) in Python

Introduction

Normally, when defining a function, you specify the exact number of parameters it should accept. However, there are situations where you may not know in advance how many arguments will be passed to a function.

For example:

  • A calculator function may need to add 2, 5, or even 20 numbers.
  • A user registration system may receive different sets of information.
  • A configuration function may need to accept various optional settings.

In such situations, Python provides variable-length arguments, which allow a function to accept any number of arguments.

Python supports two types of variable-length arguments:

  • *args (Variable-Length Positional Arguments)
  • **kwargs (Variable-Length Keyword Arguments)

These features make functions more flexible and powerful, especially in large applications, frameworks, APIs, and libraries.

What are Variable-Length Arguments?

Variable-length arguments allow a function to accept a varying number of arguments instead of a fixed number.

Normally:


def add(a, b):
    return a + b

This function only accepts two arguments.


add(10, 20)

But what if you want to add 3, 5, or 10 numbers?

That’s where *args becomes useful.

Similarly, when you want to accept multiple named arguments, you can use **kwargs.

Why Use Variable-Length Arguments?

Variable-length arguments are useful when:

  • The number of inputs is unknown.
  • Building reusable functions.
  • Creating APIs.
  • Processing dynamic user data.
  • Developing frameworks and libraries.

They make functions flexible and scalable.

Understanding *args

The *args parameter allows a function to accept any number of positional arguments.

Syntax


def function_name(*args):
    # code block

The asterisk (*) tells Python to collect all positional arguments into a tuple.

Simple *args Example


def show_numbers(*args):
    print(args)
show_numbers(10, 20, 30)

Output:

(10, 20, 30)

Python stores the values inside a tuple.

Iterating Through *args

Example:


def display_names(*names):
    for name in names:
        print(name)
display_names(
    "John",
    "Emma",
    "David"
)

Output:

John
Emma
David

Using *args for Addition

Example:


def add_numbers(*numbers):
    total = 0
    for num in numbers:
        total += num
    return total
print(add_numbers(10, 20, 30))

Output:

60

The function works regardless of how many numbers are passed.

Passing Different Numbers of Arguments

Example:


def show_values(*values):
    print(values)

show_values(1)
show_values(1, 2)
show_values(1, 2, 3, 4)

Output:

(1,) (1, 2) (1, 2, 3, 4)

This demonstrates the flexibility of *args.

Understanding **kwargs

The **kwargs parameter allows a function to accept any number of keyword arguments.

Syntax


def function_name(**kwargs):
    # code block

The double asterisk (**) tells Python to collect keyword arguments into a dictionary.

Simple **kwargs Example


def student_details(**kwargs):
    print(kwargs)
student_details(
    name="John",
    age=20
)

Output:

{‘name’: ‘John’, ‘age’: 20}

Python stores the data in a dictionary.

Accessing Values from **kwargs

Example:


def employee(**details):
    print(details["name"])
    print(details["department"])
employee(
    name="Emma",
    department="IT"
)

Output:

Emma
IT

Iterating Through **kwargs

Example:


def show_details(**details):
    for key, value in details.items():
        print(key, value)
show_details(
    name="David",
    age=25
)

Output:

name David
age 25

Difference Between *args and **kwargs

Feature *args **kwargs
Accepts Positional Arguments Keyword Arguments
Stored As Tuple Dictionary
Symbol * **
Example (10, 20, 30) {‘name’:’John’}

Using *args and **kwargs Together

Python allows both in the same function.

Example:


def employee(*args, **kwargs):
    print(args)
    print(kwargs)
employee(
    101,
    102,
    name="John",
    age=25
)

Output:

(101, 102)
{‘name’: ‘John’, ‘age’: 25}

Order of Parameters

When combining parameters, follow this order:


def function(
    normal_parameter,
    *args,
    **kwargs
):
    pass

Example:


def demo(a, *args, **kwargs):
    print(a)

This is the correct structure.

Real-Life Example: Shopping Cart


def cart_total(*prices):
    return sum(prices)
print(
    cart_total(
        100,
        200,
        300
    )
)

Output:

600

Customers can purchase any number of items.

Real-Life Examples:

1. Student Registration


def register_student(**details):
    for key, value in details.items():
        print(key, value)
register_student(
    name="Emma",
    age=21,
    course="Python"
)

Output:

name Emma
age 21
course Python

Different students may provide different information.

2. Employee Management


def add_employee(
    *employee_ids
):
    for emp_id in employee_ids:
        print(emp_id)
add_employee(
    101,
    102,
    103
)

Output:

101
102
103

3. Website Settings


def website_config(**settings):
    print(settings)
website_config(
    theme="dark",
    language="English"
)

Output:

{‘theme’: ‘dark’, ‘language’: ‘English’}

Configuration settings are often dynamic.

4. User Profile


def create_profile(**profile):
    print(profile)
create_profile(
    name="John",
    city="Delhi",
    age=25
)

Output:

{‘name’: ‘John’, ‘city’: ‘Delhi’, ‘age’: 25}

Users may provide varying amounts of information.

Advantages of *args and **kwargs

1. Flexibility

Functions can accept varying amounts of data.

2. Reusability

One function can handle multiple scenarios.

3. Cleaner Code

Reduces the need for many overloaded functions.

4. Dynamic Data Handling

Useful for forms, APIs, and user input.

5. Widely Used in Frameworks

Popular frameworks like Django and Flask use them extensively.

Common Mistakes

1. Forgetting the Asterisk

Incorrect:


def show_numbers(args):
    pass

This is just a normal parameter.

Correct:


def show_numbers(*args):
    pass

2. Forgetting Double Asterisks

Incorrect:


def show_details(kwargs):
    pass

Correct:


def show_details(**kwargs):
    pass

3. Assuming *args is a List


def demo(*args):
    print(type(args))

Output:

<class ‘tuple’>

*args is a tuple, not a list.

4. Assuming **kwargs is a List


def demo(**kwargs):
    print(type(kwargs))

Output:

<class ‘dict’>

**kwargs is a dictionary.

5. Incorrect Parameter Order

Incorrect:


def demo(**kwargs, *args):
    pass

Output:

SyntaxError

Correct:


def demo(*args, **kwargs):
    pass

Best Practices

1. Use Meaningful Names

Although args and kwargs are conventions, descriptive names can help readability.


def display_students(*student_names):

2. Use *args Only When Needed

If the number of arguments is fixed, use normal parameters.

3. Use **kwargs for Optional Settings

Perfect for configuration options and form data.

4. Document Expected Inputs

Clearly explain what arguments the function expects.

5. Combine with Validation

Always validate user input when processing dynamic data.

Conclusion

Variable-length arguments are one of Python’s most powerful function features. Using *args, you can accept any number of positional arguments, while **kwargs allows you to handle any number of keyword arguments. Together, they provide flexibility, improve code reusability, and make functions adaptable to changing requirements.

Related Python Tutorials