[Python] Correct annotation for "apply" function

Discussão em 'Python' iniciado por Stack, Fevereiro 7, 2025.

  1. Stack

    Stack Membro Participativo

    In Python-3.10 (it must be this version) I want to add better annotation for my apply function:

    from typing import TypeVar, Callable, Sequence, Any

    T = TypeVar('T')

    def apply(fn: Callable[..., T], vals: Sequence[Any]) -> T:
    return fn(*vals)

    def f(a: int, b: int) -> int:
    return a + b

    print(apply(f, (1, 2)))


    Because in this code, the type annotation "hides" the connection between vals and fn arguments, so mypy can't check types and number of arguments correctly.

    What have I tried:

    1. using ParamSpec


    from typing import ParamSpec

    P = ParamSpec('P')

    def apply(fn: Callable[P, T], vals: P) -> T:
    return fn(*vals)


    which gives this error:

    tst_apply.py:6: error: Invalid location for ParamSpec "P" [valid-type]
    tst_apply.py:6: note: You can use ParamSpec as the first argument to Callable, e.g., "Callable[P, int]"
    tst_apply.py:7: error: Too few arguments [call-arg]
    Found 2 errors in 1 file (checked 1 source file)

    2. using ParamSpec.args


    from typing import ParamSpec

    P = ParamSpec('P')

    def apply(fn: Callable[P, T], vals: P.args) -> T:
    return fn(*vals)


    which gives this error:

    tst_apply.py:7: error: Too few arguments [call-arg]
    Found 1 error in 1 file (checked 1 source file)

    3. using TypeVarTuple as suggested in Daraan's answer Revision 1:


    Even though TypeVarTuple is available only from python-3.11, I can import it from typing_extensions, but it still doesn't work - it works when I change vals: *Ts to *vals: *Ts but that's unusable for me:

    Ts = TypeVarTuple('Ts')

    def apply(fn: Callable[[*Ts], T], vals: *Ts) -> T:
    return fn(*vals)


    which gives this error:

    tst_apply.py:7: error: invalid syntax [syntax]
    def apply(fn: Callable[[*Ts], T], vals: *Ts) -> T:
    ^
    Found 1 error in 1 file (errors prevented further checking)

    4. using Tuple[*Ts] for TypeVarTuple:


    def apply(fn: Callable[[*Ts], T], vals: Tuple[*Ts]) -> T:
    return fn(*vals)


    which gives this error:

    tst_apply.py:7: error: invalid syntax. Perhaps you forgot a comma? [syntax]
    def apply(fn: Callable[[*Ts], T], vals: Tuple[*Ts]) -> T:
    ^
    Found 1 error in 1 file (errors prevented further checking)

    Question:


    Is there a way to annotate this so the connection between fn parameters and vals is not lost?

    Continue reading...

Compartilhe esta Página