显式元组泛型扩展

问题描述 投票:0回答:1

简化场景(游乐场):

from typing import TypeVar, reveal_type

class A: ...
class B(A): ...
class C(A): ...

T = TypeVar('T', bound=A)

def fun(*args: T) -> tuple[T, ...]: return args

# one parameter
reveal_type(fun(A()))  # Revealed type is "builtins.tuple[gargs.A, ...]"
reveal_type(fun(B()))  # Revealed type is "builtins.tuple[gargs.B, ...]"
reveal_type(fun(C()))  # Revealed type is "builtins.tuple[gargs.C, ...]"

# multiple parameters, same type
reveal_type(fun(A(), A()))  # Revealed type is "builtins.tuple[gargs.A, ...]"
reveal_type(fun(B(), B()))  # Revealed type is "builtins.tuple[gargs.B, ...]"
reveal_type(fun(C(), C()))  # Revealed type is "builtins.tuple[gargs.C, ...]"

# multiple parameters, different types
reveal_type(fun(A(), B()))  # Revealed type is "builtins.tuple[gargs.A, ...]"
reveal_type(fun(B(), C()))  # Revealed type is "builtins.tuple[gargs.A, ...]"
reveal_type(fun(C(), A()))  # Revealed type is "builtins.tuple[gargs.A, ...]"

有没有办法注释

fun
来教导
mypy
fun
在后三种情况下应该返回
tuple[A, B]
tuple[B, C]
tuple[C, A]

python mypy python-typing
1个回答
0
投票

这就是

TypeVarTuple
的用途:

(游乐场)

from typing import TypeVarTuple

Ts = TypeVarTuple('Ts')

def fun(*args: *Ts) -> tuple[*Ts]: return args
reveal_type(fun(A()))       # tuple[A]
reveal_type(fun(B()))       # tuple[B]
reveal_type(fun(C()))       # tuple[C]

reveal_type(fun(A(), A()))  # tuple[A, A]
reveal_type(fun(B(), B()))  # tuple[B, B]
reveal_type(fun(C(), C()))  # tuple[C, C]

reveal_type(fun(A(), B()))  # tuple[A, B]
reveal_type(fun(B(), C()))  # tuple[B, C]
reveal_type(fun(C(), A()))  # tuple[C, A]

一个缺点是

TypeVarTuple
还不能被绑定,所以我们必须使用一些技巧:

(游乐场)

from typing import Any, Never, Protocol, TypeVarTuple

Ts = TypeVarTuple('Ts')

class F1(Protocol):
    def __call__(self, /, *args: *Ts) -> tuple[*Ts]: ...

class F2(Protocol):
    def __call__(self, /, *args: A) -> Never: ...

def fun_decorator(fun: Any) -> F1 | F2:
    return fun

@fun_decorator
def fun(*args: *Ts) -> tuple[*Ts]: return args
reveal_type(fun(D()))            # error
reveal_type(fun(D(), A()))       # error
reveal_type(fun(C(), B(), D()))  # error

装饰后,

fun
具有
F1 | F2
类型。两者都接受可变数量的参数,但
F2
要求其参数必须全部为
A
类型。返回类型推导为
tuple[*Ts] | Never
,本质上就是
tuple[*Ts]

© www.soinside.com 2019 - 2024. All rights reserved.