1.背景
我经常只为类型检查器导入python模块,比如
mypy
例如:
if TYPE_CHECKING:
import bar
然后我会使用模块
bar
在整个代码中都有类型提示。这些类型提示仅对类型检查器可见,而
酒吧
在实时运行代码时,它本身不会被导入。
以这种方式给出类型提示效果很好。然而,当试图
铸造
类型,我收到“找不到模块”错误。
2.示例
让我们考虑以下示例。我有三个模块/文件:
这是
test.py
:
# FILE: TEST.PY
# =============
from typing import *
import foo
if TYPE_CHECKING:
import bar
def my_func():
foo_obj:foo.Foo = foo.Foo()
bar_obj:bar.Bar = foo_obj.get_something()
类型检查器
mypy
抱怨最后一行。现在让我们来看看函数
get_something()
在里面
foo.py
找出原因:
# FILE: FOO.PY
# =============
import bar
class Foo:
def __init__(self) -> None:
...
return
def get_something(self) -> Union[bar.Bar, str]:
...
return something
类型检查器
mypy
知道这一点
get_something()
返回a
Bar()
-对象或字符串。因此,
mypy
抱怨。很公平。
现在我知道了一个事实,在这种特殊情况下-
get_something()
将
返回a
Bar()
-对象。类型检查器不必担心。因此,我的第一反应是用断言或强制转换向类型检查器提供提示:
# ASSERTION:
# Give hint to type checker with an assertion
something = foo_obj.get_something()
assert isinstance(something, bar.Bar)
bar_obj:bar.Bar = something
# CAST:
# Give hint to type checker with a cast
bar_obj:bar.Bar = cast(foo_obj.get_something(), bar.Bar)
在我看来,演员阵容的方法最优雅,因为它可以以最小的开销完成。此外,强制转换没有运行时效果。在运行时
cast()
函数本质上是
nop()
只有类型检查器才能看到演员阵容。
3.问题
不幸的是,转换在运行时抛出“找不到模块”错误。这不是我所期望的。毕竟,在运行时应该完全忽略强制转换!我看到了一些处理这个问题的方法,但它们都有其缺点:
你知道怎么告诉字体检查器吗
mypy
-除了演员阵容或断言之外——
foo_obj.get_something()
将
返回a
Bar()
-在这种情况下的对象?或者,是否有一种方法可以在运行时执行强制转换而不会导致代码崩溃(因为缺少模块)?