Weekly - issue 39

Python Asterisk and Slash Special Function Parameters

The asterisk (*) and forward slash (/) define whether you can pass positional or keyword arguments to your functions.

Left sideDividerRight side
Positional-only arguments/Positional or keyword arguments
Positional or keyword arguments*Keyword-only arguments
def asterisk_usage(either, *, keyword_only):
    print(either, keyword_only)

asterisk_usage(either="Frank", keyword_only="Dean")
asterisk_usage("Frank", keyword_only="Dean")

asterisk_usage("Frank", "Dean") # wrong
def print_three_members(member1, member2, *): # wrong
    pass

# Accepts only keyword arguments
def print_three_members(*, member1, member2, member3):
    print(member1, member2, member3)
def slash_usage(positional_only, /, either):
    print(positional_only, either)

slash_usage("Frank", either="Dean")
slash_usage("Frank", "Dean")

slash_usage(positional_only="Frank", either="Dean") # wrong

# Accepts only positional arguments
def print_three_members(member1, member2, member3, /):
    print(member1, member2, member3)
# Use both the asterisk and slash
# / must be ahead of *
def print_four_members(member1, member2, /, *, member3):
    print(member1, member2, member3)

Python Type Hints - *args and **kwargs

# args: Tuple[int, ...]
# kwargs: Dict[str, int]
def variable(*args: int, **kwargs: int) -> None:
    ...

* always binds to a tuple, and ** always binds to a dict with string keys.

Because of this restriction, type hints only need you to define the types of the contained arguments. The type checker automatically adds the Tuple[_, ...] and Dict[str, _] container types.

Other ways to try:

  • using a type union

    def variable(*args: int, **kwargs: int | str | bool) -> None:
        ...
  • using Any type

    def variable(*args: int, **kwargs: Any) -> None:
        ...
  • using TypedDict (Python 3.12)

    from typing import Required, TypedDict, Unpack
    
    # all the arguments are optional, only key2 is required
    class Options(TypedDict, total = False):
        key1: int
        key2: Required[str]
        key3: bool
    
    def variable(*args: int, **kwargs: Unpack[Options]) -> None:
        ...

    But may be better to pass keyword arguments with asterisk(*) special function parameters.