考虑以下代码:
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)
,但这也不起作用。
绑定到
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
的情况并没有什么不同,但往往“看起来”不那么令人惊讶。)