如何根据运行时条件指定类型

How to specify type based on runtime condition

我正在使用 mypy 和协议,并且 运行 进入了一个地方,如果可能的话我希望输入提示,但我无法弄清楚我应该如何设置它以便 mypy 不会出错。

考虑以下示例:

class TProtocol(Protocol):
    t: str

@attrs(auto_attribs=True)
class T:
    t: str
    t2: str

@attrs(auto_attribs=True)
class T2:
    t: str

def func(var: TProtocol) -> None:
    if some_condition:
        var: T
        reveal_type(var)
    else:
        reveal_type(var)

虽然非常人为,但它说明了我的目标,即我有一些 运行时间条件,如果满足,我会根据代码库的知识知道该变量的类型。然后我想将这些知识传递给 mypy,以便进一步的类型检查使用该类型。

同样的例子可以用联合来代替。进行了一些 运行 时间检查,它根据代码库的知识明确地告诉我我拥有哪一种类型。然后我想明确地告诉 mypy 哪种类型用于根据外部知识进行进一步的类型检查。

上面的例子引发了一个错误,指出 var 已经被定义。我尝试了 allow_redefinition 选项,但它没有改变输出。

使用typing.cast强制将变量声明为特定类型。这忽略了任何其他键入信息,并且也适用于运行时分支。

def func(var: TProtocol) -> None:
    reveal_type(var)         # line 21
    if some_condition:
        var = cast(T, var)   # line 23
        reveal_type(var)
    else:
        var = cast(T2, var)  # line 26
        reveal_type(var)

这使得 mypy 以不同的方式处理 var 的每个强制转换事件,即在每个分支之前和内部:

type_tests.py:21: note: Revealed type is 'type_tests.TProtocol'
type_tests.py:24: note: Revealed type is 'type_tests.T'
type_tests.py:27: note: Revealed type is 'type_tests.T2'