[Python] Returning a generic value from a generic function wrapper erases the type argument

Discussão em 'Python' iniciado por Stack, Junho 11, 2025.

  1. Stack

    Stack Membro Participativo

    In the following Python code, I define a generic function wrapper which takes a function of type T → T and replaces it by a function without arguments returning an instance of Delay[T]. This instance simply stores the original function so that it can be called later.

    from collections.abc import Callable

    class Delay[T]:
    def __init__(self, wrapped: Callable[[T], T]):
    self.wrapped = wrapped

    def wrapper[T](wrapped: Callable[[T], T]) -> Callable[[], Delay[T]]:
    def wrapping() -> Delay[T]:
    return Delay(wrapped)

    return wrapping


    When using this wrapper with a normal function, the type checker is happy:

    @wrapper
    def fun1(arg: str) -> str:
    return arg

    reveal_type(fun1) # mypy says: "def () -> Delay[builtins.str]"
    reveal_type(fun1()) # mypy says: "Delay[builtins.str]"
    reveal_type(fun1().wrapped) # mypy says: "def (builtins.str) -> builtins.str"
    reveal_type(fun1().wrapped("test")) # mypy says: "builtins.str"


    However, when the wrapped function is generic, the type argument somehow gets erased:

    @wrapper
    def fun2[T](arg: T) -> T:
    return arg

    reveal_type(fun2) # mypy says: "def () -> Delay[Never]"
    reveal_type(fun2()) # mypy says: "Delay[Never]"
    reveal_type(fun2().wrapped) # mypy says: "def (Never) -> Never"
    reveal_type(fun2().wrapped("test")) # mypy says: "Never"


    I would expect the type checker to infer generic types in the first three reveal_type() lines, and to infer str on the last one. Note that pyright seems to exhibit similar behavior.

    Is there something invalid with the type annotations in my code? Is this a known limitation of the Python type system, or a bug in mypy and pyright?

    Continue reading...

Compartilhe esta Página