What is an argument in Python?

Discover what an argument is in Python: definition, types of arguments (positional, keyword, *args, **kwargs), practical examples and best practices.
11 min read
Believemy logo

Definition of an argument in Python

In Python, an argument is a value that you pass to a function or method when calling it. Arguments provide input data to a function so that it can perform its processing. They represent the concrete information you pass to a function, as opposed to parameters, which are the variables defined in the function signature using the def keyword.

If you want to fully master functions and arguments in Python, our comprehensive Python course will guide you step by step through learning these fundamental concepts.

Good to know

The distinction between argument and parameter is subtle but important: a parameter is the variable in the function definition, while an argument is the actual value passed during the call.

PYTHON
# Here, 'name' is a parameter
def greet(name):
    print(f"Hello, {name}!")

# Here, "Alice" is an argument
greet("Alice")
# Output: Hello, Alice!

This distinction is essential for understanding how functions work in Python and for communicating effectively with other developers.

 

The different types of arguments in Python

Python offers great flexibility in how you can pass arguments to a function. Understanding each type of argument will allow you to write more readable, maintainable, and powerful code.

Positional arguments

Positional arguments are the simplest and most common. They are passed in the exact order in which the parameters are defined in the function signature. Order matters: the first argument corresponds to the first parameter, the second to the second, and so on.

PYTHON
def introduce(first_name, last_name, age):
    print(f"{first_name} {last_name} is {age} years old.")

# Arguments are passed in order: first_name, last_name, age
introduce("Marie", "Dupont", 30)
# Output: Marie Dupont is 30 years old.

# Be careful with the order! Swapping arguments changes the result
introduce("Dupont", "Marie", 30)
# Output: Dupont Marie is 30 years old.

As you can see, swapping the order of positional arguments produces an incorrect result. This is why it is crucial to respect the parameter order when calling a function.

 

Keyword arguments

Keyword arguments are passed by explicitly specifying the name of the parameter they correspond to. This approach has two major advantages: you no longer need to respect the parameter order, and your code becomes much more readable.

PYTHON
def introduce(first_name, last_name, age):
    print(f"{first_name} {last_name} is {age} years old.")

# With keyword arguments, order does not matter
introduce(age=30, last_name="Dupont", first_name="Marie")
# Output: Marie Dupont is 30 years old.

# You can also mix positional and keyword arguments
introduce("Marie", age=30, last_name="Dupont")
# Output: Marie Dupont is 30 years old.
Warning

When mixing positional and keyword arguments, positional arguments must always be placed before keyword arguments. Otherwise, Python will raise a SyntaxError.

 

Default arguments

Default arguments are defined directly in the function signature. They allow you to make certain parameters optional: if you do not provide a value for these parameters, the default value will be used.

PYTHON
def create_profile(name, role="user", active=True):
    return {
        "name": name,
        "role": role,
        "active": active
    }

# Call with only the required argument
profile1 = create_profile("Alice")
print(profile1)
# {'name': 'Alice', 'role': 'user', 'active': True}

# Call overriding one default argument
profile2 = create_profile("Bob", role="admin")
print(profile2)
# {'name': 'Bob', 'role': 'admin', 'active': True}

# Call overriding all arguments
profile3 = create_profile("Charlie", role="moderator", active=False)
print(profile3)
# {'name': 'Charlie', 'role': 'moderator', 'active': False}
Warning

Beware of mutable default values! Never use a list, a dict, or a set as a default value. Instead, use None and create the mutable object inside the function body.

PYTHON
# ❌ BAD PRACTICE: mutable list as default value
def add_element(element, lst=[]):
    lst.append(element)
    return lst

print(add_element(1))  # [1]
print(add_element(2))  # [1, 2] ← The same list is reused!

# ✅ GOOD PRACTICE: use None as default value
def add_element(element, lst=None):
    if lst is None:
        lst = []
    lst.append(element)
    return lst

print(add_element(1))  # [1]
print(add_element(2))  # [2] ← Expected behavior

 

Variable arguments with *args

The *args syntax allows you to pass a variable number of positional arguments to a function. These arguments are grouped into a tuple accessible inside the function. This is particularly useful when you don't know in advance how many arguments will be passed.

PYTHON
def calculate_sum(*args):
    print(f"Type of args: {type(args)}")
    print(f"Values received: {args}")
    return sum(args)

# Call with a variable number of arguments
result1 = calculate_sum(1, 2, 3)
print(f"Sum: {result1}")
# Type of args: 
# Values received: (1, 2, 3)
# Sum: 6

result2 = calculate_sum(10, 20, 30, 40, 50)
print(f"Sum: {result2}")
# Sum: 150

You can also combine *args with regular parameters:

PYTHON
def display_scores(player, *scores):
    average = sum(scores) / len(scores) if scores else 0
    print(f"{player} - Scores: {scores} - Average: {average:.1f}")

display_scores("Alice", 85, 92, 78, 95)
# Alice - Scores: (85, 92, 78, 95) - Average: 87.5

 

Variable arguments with **kwargs

The **kwargs syntax works similarly to *args, but for keyword arguments. The arguments are grouped into a dict (dictionary) accessible inside the function.

PYTHON
def create_user(**kwargs):
    print(f"Type of kwargs: {type(kwargs)}")
    for key, value in kwargs.items():
        print(f"  {key} = {value}")
    return kwargs

create_user(name="Alice", age=30, city="Paris", email="alice@example.com")
# Type of kwargs: 
#   name = Alice
#   age = 30
#   city = Paris
#   email = alice@example.com

The combination of *args and **kwargs is very powerful and commonly used in Python libraries:

PYTHON
def flexible_function(*args, **kwargs):
    print(f"Positional arguments: {args}")
    print(f"Keyword arguments: {kwargs}")

flexible_function(1, 2, 3, name="Alice", age=30)
# Positional arguments: (1, 2, 3)
# Keyword arguments: {'name': 'Alice', 'age': 30}

 

Parameter order in Python

Python enforces a strict order in the definition of function parameters. Here is the order to follow:

PositionParameter typeExample
1Required positional parametersa, b
2Parameters with default valuesc=10
3*args (variable positional arguments)*args
4Keyword-only parametersd, e=20
5**kwargs (variable keyword arguments)**kwargs
PYTHON
# Example with all parameter types
def complete_function(a, b, c=10, *args, d, e=20, **kwargs):
    print(f"a={a}, b={b}, c={c}")
    print(f"args={args}")
    print(f"d={d}, e={e}")
    print(f"kwargs={kwargs}")

complete_function(1, 2, 3, 4, 5, d=100, e=200, extra="test")
# a=1, b=2, c=3
# args=(4, 5)
# d=100, e=200
# kwargs={'extra': 'test'}

Parameters placed after *args (here d and e) are keyword-only parameters: they must be passed as keyword arguments.

 

Argument unpacking

Python allows you to unpack data structures to pass them as arguments to a function. This is an extremely useful technique that makes your code more elegant.

Unpacking with * (lists and tuples)

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

# Unpack a list
numbers = [10, 20, 30]
result = add(*numbers)
print(result)  # 60

# Unpack a tuple
coordinates = (5, 10, 15)
result = add(*coordinates)
print(result)  # 30

 

Unpacking with ** (dictionaries)

PYTHON
def create_profile(name, age, city):
    return f"{name}, {age} years old, lives in {city}"

# Unpack a dictionary
info = {"name": "Alice", "age": 30, "city": "Paris"}
profile = create_profile(**info)
print(profile)  # Alice, 30 years old, lives in Paris

Unpacking is particularly useful with functions like zip or enumerate where you manipulate collections of data.

 

Arguments and lambda functions

lambda functions accept the same types of arguments as regular functions defined with def, although their usage is generally more concise:

PYTHON
# Lambda with positional arguments
multiply = lambda x, y: x * y
print(multiply(3, 4))  # 12

# Lambda with default argument
greet = lambda name, greeting="Hello": f"{greeting}, {name}!"
print(greet("Alice"))           # Hello, Alice!
print(greet("Bob", "Hi"))       # Hi, Bob!

# Lambda with *args
add = lambda *args: sum(args)
print(add(1, 2, 3, 4))  # 10

 

Best practices for arguments in Python

Here are the essential best practices to follow when working with arguments in Python:

1. Name your parameters descriptively

PYTHON
# ❌ BAD: non-descriptive names
def calc(a, b, c):
    return a * b * (1 + c)

# ✅ GOOD: descriptive names
def calculate_total_price(unit_price, quantity, tax_rate):
    return unit_price * quantity * (1 + tax_rate)

 

2. Limit the number of arguments

If a function requires more than 4-5 arguments, consider using a dict, a dataclass, or a namedtuple to group related parameters:

PYTHON
from dataclasses import dataclass

# ❌ Too many arguments
def create_order(client_name, client_email, client_phone, 
                 product_name, product_price, quantity, discount):
    pass

# ✅ Use dataclasses to group them
@dataclass
class Client:
    name: str
    email: str
    phone: str

@dataclass
class Product:
    name: str
    price: float

def create_order(client: Client, product: Product, quantity: int, discount: float = 0):
    pass

 

3. Use type annotations

Type annotations improve readability and allow static analysis tools to detect errors. Combined with docstring, they make your code much more understandable:

PYTHON
def search_users(
    name: str,
    min_age: int = 0,
    max_age: int = 120,
    active: bool = True
) -> list[dict]:
    """Search for users based on the given criteria.
    
    Args:
        name: The name or part of the name to search for.
        min_age: The minimum age (inclusive). Defaults to 0.
        max_age: The maximum age (inclusive). Defaults to 120.
        active: Filter only active users.
    
    Returns:
        A list of dictionaries representing the found users.
    """
    pass

 

4. Prefer keyword arguments for clarity

PYTHON
# ❌ Hard to read: what do True and 5 mean?
result = send_email("alice@example.com", "Subject", "Body", True, 5)

# ✅ Readable: each argument is explicit
result = send_email(
    recipient="alice@example.com",
    subject="Subject",
    body="Body",
    html=True,
    max_retries=5
)

 

5. Use / and * to enforce argument types

Since Python 3.8, you can use / and * to control whether arguments must be positional or keyword:

PYTHON
# Everything before / must be positional
# Everything after * must be keyword
def configure(host, port, /, *, timeout=30, retries=3):
    print(f"Connecting to {host}:{port} (timeout={timeout}, retries={retries})")

# ✅ Correct
configure("localhost", 8080, timeout=60)

# ❌ Error: host and port must be positional
# configure(host="localhost", port=8080, timeout=60)

# ❌ Error: timeout must be keyword
# configure("localhost", 8080, 60)

 

Pass by reference or by value?

In Python, arguments are passed by assignment (sometimes called pass by object reference). This means that the local variable in the function points to the same object as the argument passed. The behavior then depends on the type of object:

Object typeMutable?Behavior
int, float, str, tupleNo (immutable)Modifications create a new object
list, dict, setYes (mutable)Modifications affect the original object
PYTHON
# With an immutable object (int)
def modify_number(n):
    n = n + 10
    print(f"Inside the function: n = {n}")

value = 5
modify_number(value)
print(f"After the call: value = {value}")
# Inside the function: n = 15
# After the call: value = 5 ← Not modified!

# With a mutable object (list)
def modify_list(lst):
    lst.append(4)
    print(f"Inside the function: lst = {lst}")

my_list = [1, 2, 3]
modify_list(my_list)
print(f"After the call: my_list = {my_list}")
# Inside the function: lst = [1, 2, 3, 4]
# After the call: my_list = [1, 2, 3, 4] ← Modified!
Good to know

If you want to avoid unintended modifications to a mutable object, pass a copy of the object to the function using for example my_list.copy() or my_list[:].

 

Frequently asked questions

Question

What is the difference between an argument and a parameter in Python?

A parameter is the variable declared in the function definition (for example def greet(name) where name is the parameter). An argument is the actual value you pass when calling that function (for example greet("Alice") where "Alice" is the argument). In practice, the two terms are often used interchangeably, but knowing this distinction helps you better understand Python's official documentation.

 

Question

When should you use *args and **kwargs?

Use *args when you want a function to accept a variable number of positional arguments (for example, a function that calculates the sum of N numbers). Use **kwargs when you want to accept a variable number of keyword arguments (for example, a configuration function with many optional settings). Both syntaxes are particularly useful in decorators, wrapper functions, and functions that need to forward arguments to other functions.

 

Question

Why should you not use a list as a default value?

In Python, default parameter values are evaluated only once, at the time of function definition, not at each call. If you use a list (or any other mutable object) as a default value, that same instance will be shared across all function calls. This can cause bugs that are difficult to track down. The recommended solution is to use None as the default value and create a new mutable object inside the function body.

 

Question

How can you learn to master arguments and functions in Python?

To master arguments in Python, we recommend practicing regularly by writing your own functions with different types of arguments. Start with positional arguments, then progressively explore keyword arguments, default values, *args, and **kwargs. For a structured and comprehensive learning experience, our dedicated Python course guides you from the basics to advanced concepts, with practical exercises and real-world projects that will allow you to fully master these essential concepts.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.