为什么 mypy/PyCharm/etc 没有检测到 Type[T] 的类型错误?

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

考虑以下代码:

def verify(schema: Type[T], data: T) -> None:
    pass

verify(int, "3")
verify(float, "3")
verify(str, "3")

我希望前两个

verify()
调用显示为类型错误,而最后一个则不会。

但是,在 PyCharm 和 mypy 中,它们都没有出现类型错误。我尝试为严格性和错误代码启用所有可能的标志,但什么都没有。

如何让类型检查器对此进行类型检查?为什么会失败?

apischema
这样的库依赖于这样的功能来进行类型检查,例如
apischema.serialize(MyDataclass, my_dataclass)
,但这也不起作用。

python pycharm mypy python-typing typing
1个回答
2
投票

绑定到

T
的类型不是由任何单个参数决定的;它是以满足要求的方式选择的。由于
object
int
-和-
str
float
-和-
str
的最接近的公共超类型),在这些情况下,
T
绑定到
object
。 (对于
verify(str, "3")
T
绑定到
str
的原因相同:它是
str
str
的平凡最接近的超类型)。

您可以通过让

verify
返回
schema
,然后询问
mypy
返回值有什么来看到这一点。

def verify(schema: Type[T], data: T) -> Type[T]:
    return schema

reveal_type(verify(int, "3"))  # builtins.object
reveal_type(verify(float, "3"))  # builtins.object
reveal_type(verify(str, "3"))  # builtins.str

如果你可以枚举你希望传递给

schema
的类型,你可以通过使
T
成为一个constrained类型变量来部分解决问题。

T = TypeVar('T', int, str, float)

def verify(schema: Type[T], data: T) -> None:
    ...

由于

T
不能再绑定到
object
,您的前两个示例将无法按要求进行类型检查。


注意像下面这样的东西仍然会通过:

class MyFloat(float):
    pass


verify(MyFloat, 3.14)

因为

T
将绑定到
float
,这是
float
MyFloat
最接近的公共超类。 (这与
object
的情况并没有什么不同,但往往“看起来”不那么令人惊讶。)

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