How to Implement Positional Type Hinting for Iterables in Python?

]I’ve recently written a piece of code that looks something like this:

def display_info(input_data: tuple[int, str, dict]):
    numeric_value, text, key_value_store = input_data
    print(numeric_value, text, key_value_store)

However, I’ve noticed that this type hinting approach might not be the most flexible. The function performs adequately with any iterable object ordered as int, str, dict that is passed to ‘input_data’, not just tuples.

display_info((1, 'foo', {}))  # This executes perfectly and satisfies the type checker.
display_info([1, 'foo', {}])  # This also executes perfectly but doesn't satisfy the type checker.
display_info(i for i in (1, 'foo', {}))  # Once more this works but doesn't satisfy the type checker.

While users can manually convert their input into a tuple before passing it to the function as shown below,

def get_information() -> list:
    """Simulating data retrieval from some external source."""
    return [1, 'foo', {}]

display_info(tuple(get_information()))  # This functions but involves unnecessary steps.

I’d prefer not to require them to perform this additional step which is essentially unnecessary.

So I have two main inquiries. Does Python provide a way to implement positional type hints for iterables? If such functionality does not currently exist within Python’s typing system could you explain why it might be absent? It would be interesting if there were potential enhancements on this concept in future versions of Python. Thank you!

1 Like

I don’t think there is a way to specify the types in this situation[1], but I would change the signature and unpack arguments using * when the input is an iterable, which is more flexible and readable anyway:

# the arguments are now visible in the signature
def display_info(numeric_value: int, text: str, key_value_store: dict):
    print(numeric_value, text, key_value_store)

display_info(1, 'foo', {})  # positional arguments
display_info(*(1, 'foo', {}))
display_info(*[1, 'foo', {}])
display_info(*(i for i in (1, 'foo', {})))
display_info(*(1, 'foo'), key_value_store={})  # partial unpacking and a keyword argument

I’m not sure when I would want to define a fixed-length, heterogenous iterable type…certainly not in a signature.

  1. if I’m wrong I’m sure someone will mention it ↩︎

1 Like

Positional hints for iterables would imply that you’d have a program regularly using iterables with “magic” indexes/ordering. I’ve found magic indexes to be brittle and avoid them. Therefore I’m not surprised there’d be a lack of a way to type-hint that pattern.

1 Like