Guide to Type Hinting *args and **kwargs in Python

When working with Python, *args and **kwargs allow you to write flexible and dynamic functions.

Type hinting allows you to specify the expected types for these arguments.

In this tutorial, you will learn how to type hint *args and **kwargs in various cases.

 

 

Type Hinting *args and **kwargs

*args lets you pass a variable number of positional arguments to a function, while **kwargs allows for an arbitrary number of keyword arguments.

You can use the tuple type to specify the types of the elements in *args.

from typing import Tuple
def print_numbers(*args: Tuple[int, ...]) -> None:
    for number in args:
        print(number)
print_numbers(1, 2, 3, 4)

Output:

1
2
3
4

The *args: Tuple[int, ...] indicates that the function accepts any number of positional arguments, all of which must be integers.

Syntax for type hinting **kwargs

Use the dict type to define the types for **kwargs.

from typing import Dict
def print_user_data(**kwargs: Dict[str, str]) -> None:
    for key, value in kwargs.items():
        print(f"{key}: {value}")
print_user_data(name="Omar", city="Cairo")

Output:

name: Omar
city: Cairo

The **kwargs: Dict[str, str] means the function accepts keyword arguments, where keys are strings, and values are strings.

 

Type hint functions that accept args and *kwargs

To hint functions that use both *args and **kwargs, combine tuple and dictionary hints.

from typing import Tuple, Dict
def log_event(*args: Tuple[str, ...], **kwargs: Dict[str, str]) -> None:
    print("Details:")
    for arg in args:
        print(arg)
    print("Additional Info:")
    for key, value in kwargs.items():
        print(f"{key}: {value}")

log_event("Event1", "Warning", timestamp="12:30 PM", status="Active")

Output:

Details:
Event1
Warning
Additional Info:
timestamp: 12:30 PM
status: Active

The function uses both *args for positional data and **kwargs for additional descriptive information.

 

Type Hinting Varying Arguments

To handle a function accepting any type of argument with type hints, use Any.

from typing import Any
def flexible_function(*args: Any) -> None:
    for arg in args:
        print(arg)
flexible_function(1, "Ahmed", 3.5, True)

Output:

1
Ahmed
3.5
True

This method accommodates inputs of varying data types.

 

Type Hinting Keyword Arguments

To define expected types for specific keyword arguments, use TypedDict or explicit annotations.

from typing import TypedDict
class UserInfo(TypedDict):
    name: str
    age: int
def display_user_info(**kwargs: UserInfo) -> None:
    for key, value in kwargs.items():
        print(f"{key}: {value}")
display_user_info(name="Mona", age=25)

Output:

name: Mona
age: 25

Type hint functions with positional and keyword arguments

You can use Union for hints when combining positional and keyword arguments.

from typing import Union, Dict
def mix_args(*args: Union[int, str], **kwargs: Dict[str, Union[int, str]]) -> None:
    print("Args:")
    for arg in args:
        print(arg)
    print("Kwargs:")
    for key, value in kwargs.items():
        print(f"{key}: {value}")
mix_args(42, "Heba", age=30, city="Alexandria")

Output:

Args:
42
Heba
Kwargs:
age: 30
city: Alexandria

The Union[int, str] allows a mix of integers and strings.

 

Using TypedDict for Structured Keyword Arguments

TypedDict helps define complex structures for keyword arguments.

from typing import TypedDict
class Address(TypedDict):
    city: str
    postal_code: int
def show_address(**kwargs: Address) -> None:
    print(f"City: {kwargs['city']}, Postal Code: {kwargs['postal_code']}")
show_address(city="Giza", postal_code=12345)

Output:

City: Giza, Postal Code: 12345

This ensures city and postal_code must match their specified types.

 

Using various combinations of args and kwargs

Here’s a combined example showing various uses of *args and **kwargs with hints.

from typing import Tuple, Dict, Any
def process_data(*args: Tuple[str, ...], **kwargs: Dict[str, Any]) -> None:
    print("Processing data:")
    for arg in args:
        print(f"Positional: {arg}")
    for key, value in kwargs.items():
        print(f"Keyword: {key} -> {value}")
process_data("Data1", "Data2", source="API", status="Success", retries=3)

Output:

Processing data:
Positional: Data1
Positional: Data2
Keyword: source -> API
Keyword: status -> Success
Keyword: retries -> 3

The function handles a mix of positional and keyword arguments.

Leave a Reply

Your email address will not be published. Required fields are marked *