首页 > 解决方案 > 对象通过类型函数时的Mypy行为?

问题描述

在以下情况下,我似乎不理解 Mypy 的行为。此问题的代码已简化

import typing as t
...

self._store:t.Dict[str,str] = dict()
...

def set_kv(self, key:str, value:int)->t.Any:
    assert isinstance(key, six.string_types)
    assert isinstance(value, six.string_types)
    with self.__lock.write():
        self.__store[key] = value
        self.__persist()

我通过运行以下命令使用 mypy 测试此代码

mypy docido_sdk/index/test.py --ignore-missing-imports --follow-imports=error --strict-optional

现在理想情况下,这应该在 line 处引发错误self.__store[key]= value。但事实并非如此。当我删除assert isinstance(value, six.string_types)时,它才会抛出错误。isinstance 是下面给出的典型函数

def isinstance(__o: object, __t: Union[type, Tuple[Union[type, Tuple], ...]]) -> bool: ...

这是 mypy 的 bug 还是预期的行为,因为如果我理解正确isinstance应该不会影响 mypy 对value.

标签: python-3.xmypy

解决方案


当您调用时,isinstance()您正在对value.

在调用isinstance()mypy 之前认为value是一个int但实际上在运行时它可能会有所不同。isinstance()调用后value必须是一个str.

mypy 知道isinstance(),所以它把它当作一个明确的指令来覆盖它认为它知道的任何东西value并相应地更新它的模型。

同样,如果您value: Union[int, str]在检查后if isinstance(value, str): ...mypy 可以更新其对宇宙的看法并知道value现在是 astr而不是int. 在这种情况下,这似乎更直观。

这里的问题是可能的类型不相交,所以 mypy 只是将类型视为唯一可以是的类型:str.

顺便说一句,typescript 会更好地处理这种情况,因为它有一个类型never来处理这种不应该发生的情况,并且当你对never值进行意外操作时会产生错误。

Mypy 没有这个概念,因此它不善于捕捉此类问题,因为它实际上可能是故意的:类型系统仅提供提示,因此您可能有合理的代码来生成运行时断言来处理类型假设是错误的。


推荐阅读