“ cast(...)”和“ ...#type:...”之间有什么区别?

时间:2018-09-25 07:58:11

标签: python type-hinting

在Python中进行类型提示时,我有两个选项可将表达式标记为特定类型:

from typing import cast

foo = cast(str, expression)
bar = expression  # type: str

两者之间有什么区别?

给我的印象是,有时使用cast可行,而有时我必须使用注释。但是我还没有找到一种模式。不幸的是,我目前手头没有一个代码示例,而另一个却不能。

1 个答案:

答案 0 :(得分:1)

# type: ignore的意思是“请使该行中出现的与类型相关的错误保持沉默”。

cast(TYPE, EXPR)的意思是“我知道您认为X的EXPR类型,但我希望您假设该类型实际上是TYPE,好吗?”

当遇到无法解决的类型检查器的某些限制时,通常使用# type: ignore。例如,假设您尝试导入一些没有存根或类型定义的第三方库。在这种情况下,请执行以下操作:

# Results in errors like"
# error: No library stub file for module 'library_with_no_hints'
import library_with_no_hints

...通常会导致错误。但是您可以使用# type: ignore来消除该错误:

import library_with_no_hints  # type: ignore

通常,当您有其他带外信息时,cast会使类型检查器不知道某些类型X实际上仅是Y。例如:

def parse_config(assume_normalized: bool, thing: List[Union[int, str]]) -> List[int]:
    if assume_normalized:
        # The type-checker thinks that 'thing' is a List[Union[int, str]];
        # we now force it to assume it's really a List[int] instead.
        return cast(List[int], thing)
    else:
        output = []
        for item in thing:
            if isinstance(item, int):
                output.append(item)
            else:
                output.append(parse(item))
        return output

您通常会在以下情况下看到强制转换:a)您正在使用大量反序列化/序列化样式代码,并且需要将泛型类型转换为更具体的类型,b)您正在做具有多个继承的奇怪操作,或c)您的代码设计不当,并且已经陷入困境。

我个人几乎从不使用强制转换-如果可以的话,我会尽量避免使用强制转换,否则将至少使用isinstance check之类的方法,因此如果我的假设最终是错误的话,我的代码将在运行时崩溃。 >

(我也尝试忽略# type: ignore,但有时它们最终会成为一种必不可少的弊端,可以帮助您解决类型检查器中的限制。)


如果您打算在代码库中使用类型忽略或强制类型转换,还应该考虑配置类型检查器,以便在不必要的地方使用它们时向您发出警告。

例如,对于mypy,您可以传递--warn-unused-ignores--warn-unused-casts标志。