pythonpython-typing

Typing a generic iterable


I'm creating a function that yields chunks of an iterable.

How can I properly type this function so that the return value bar is of type list[int].

from typing import Any, Generator, Sequence

def chunk[T: Any, S: Sequence[T]](sequence: S, size: int) -> Generator[S, None, None]:
    for i in range(0, len(sequence), size):
        yield sequence[i : i + size]

foo: list[int] = [1,2,3]
bar = chunk(foo, 1)

Sequence[T] is invalid because TypeVar constraint type cannot be generic PylancereportGeneralTypeIssues


Solution

  • The Type Parameter Scopes section of PEP 695 – Type Parameter Syntax specifically points out that Python's typing system currently does not allow a non-concrete upper bound type, but that it may be allowed in a future extension:

    # The following generates no compiler error, but a type checker
    # should generate an error because an upper bound type must be concrete,
    # and ``Sequence[S]`` is generic. Future extensions to the type system may
    # eliminate this limitation.
    class ClassA[S, T: Sequence[S]]: ...
    

    So until that happens you simply have to spell out the generic type in the type annotations instead:

    def chunk[T](sequence: Sequence[T], size: int) -> Generator[Sequence[T], None, None]:
        for i in range(0, len(sequence), size):
            yield sequence[i : i + size]