微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Mypy 对类型类型的断言

如何解决Mypy 对类型类型的断言

在Python中,我们可以通过这种方式给变量赋值,并通过mypy的类型检查:

from typing import Type,Union


class Foo:
    pass


MyType: Type[Foo] = Foo

同样,我们也可以使用 Union 来输入

from typing import Type,Union


class Foo:
    pass


class Bar:
    pass


def func(is_bar: bool) -> Union[Type[Foo],Type[Bar]]:
    if is_bar:
        return Bar
    else:
        return Foo

知道 is_bar 的值,在调用 func 进行类型缩小后使用断言是完全合理的。

但是,断言似乎对 MyType 根本不起作用,因为 mypy 为以下代码示例提供错误

MyType = func(True)

assert MyType is Bar  
# `assert MyType is Type[Bar]` gives the same result

Test: Bar = MyType  # Incompatible types in assignment (expression
                    # has type "Union[Type[Foo],Type[Bar]]",# variable has type "Bar")

castisinstance 也不起作用。

MyType = func(True)
cast(Type[Bar],MyType)
Test: Bar = MyType  # MyType is considered `Type[Bar] | Type[Foo]`
MyType = func(True)
assert isintance(MyType,Type[Bar])
Test: Bar = MyType  # MyType is considered `Type[Bar] | Type[Foo]`

我的问题是:如何对类型的类型进行类型缩小? 或者是mypy的限制?如果是这样,解决方法是什么?

相关:

解决方法

cast 帮助器返回它的受约束参数,它实际上并没有改变它的参数被约束。

cast 到所需的 Type[...] 并分配或使用结果:

Test = cast(Type[Bar],MyType)
reveal_type(Test)  # note: Revealed type is "Type[so_testbed.Bar]"
,

另一种避免必须使用 typing.castisinstance 的解决方案是使用 typing.overload,它允许您注册单个函数的多个签名。所有用 @typing.overload 修饰的函数在运行时都会被忽略,以支持“具体”实现,因此这些函数的主体可以只是一个文字省略号。通过将 typing.overloadtyping.Literal 结合,如果传入值 True,我们可以注册函数的一个签名,如果传入值 False,我们可以注册另一个:>

from typing import Type,Union,overload,Literal


class Foo:
    pass


class Bar:
    pass


@overload
def func(is_bar: Literal[True]) -> Type[Bar]: ...


@overload
def func(is_bar: Literal[False]) -> Type[Foo]: ...


def func(is_bar: bool) -> Union[Type[Foo],Type[Bar]]:
    if is_bar:
        return Bar
    else:
        return Foo
        

test: Type[Bar] = func(True)
test2: Type[Foo] = func(False)
test3: Bar = func(True)()
test4: Foo = func(False)()

它的类型检查很好。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。