繁体   English   中英

如何帮助Mypy理解“如果不是这样”的结构?

[英]How to help mypy understand “if isinstance else” structure?

我使用一种简单的方法来处理可以是字符串或字符串列表的参数。 它故意对错误没有鲁棒性,但却是一种快速的方法。

该方法在普通的Python中可以正常工作,但是mypy不能很好地处理其类型并引发错误:

def dosomething(ext: Union[str, Iterable[str]] = ".txt"):
    exts: Tuple[str, ...] = (ext, ) if isinstance(ext, str) else ext

错误: Incompatible types in assignment (expression has type "object", variable has type "Tuple[str, ...]")

调查此问题,我发现mypy无法使用if isinstance else结构减少可用的类型选项:

def dosomething(ext: Union[str, Iterable[str]] = ".txt"):
    exts = (ext, ) if isinstance(ext, str) else ext
    reveal_type(exts)  # Revealed type is 'builtins.object'

看到mypy退回到object对我来说是一个惊喜,但是我怀疑这可能是因为str也是Iterable[str]

我想找到一种方法来避免这种意外情况,方法是在保持简单性的同时帮助mypy。

这归结为mypy如何为条件表达式推断类型的问题。 在简单的上下文中,表达式a if predicate else b推断为ab的超类型。 strIterable[str]的情况下,这是builtins.object

x = reveal_type(1 if bool() else "str")
# Revealed type is 'builtins.object'

一个例外是,如果mypy可以将谓词解析为True或False,则将类型缩小为正确的分支:

x = reveal_type(1 if True else "str")
# Revealed type is 'builtins.int'

有人希望mypy可以将isinstance检查解析为True或False,但是似乎尚未实现。 我认为这将是一个非常合理的功能要求。

但是,我们可以利用条件表达式类型的一个不错的功能,那就是它可以识别上下文。 因此,如果在期望使用其他类型的上下文中使用条件表达式,并且条件的两端都满足该类型,则类型检查将通过。 这已经讨论过这里的联盟类型的范围内,但在你的情况下,两个分支满足Iterable[str]

exts: Iterable[str] = (ext, ) if isinstance(ext, str) else ext

因此,关键只是明确指定exts的类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM