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

问题描述 投票:0回答:2

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

from typing import cast

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

两者有什么区别?

我的印象是有时使用

cast
有效,而有时我必须使用注释。但我还没有想出一个模式。不幸的是,我目前手头没有一个可以工作但另一个不能工作的代码示例。

python type-hinting
2个回答
2
投票

# 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 检查等,这样如果我的假设最终是错误的,我的代码将在运行时崩溃。

(我也尝试忽略

# type: ignore
,但有时它们最终会成为一种必要的邪恶/可以帮助您解决类型检查器中的限制。)


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

例如,使用 mypy,您可以传入

--warn-unused-ignores
--warn-unused-casts
标志。


0
投票

如果您遇到过这个问题,值得注意的是,有更好的方法将表达式转换为某种类型:

foo: str = expression

通过这种方法,您可以避免在运行时导入和调用

cast
进行静态类型检查。

© www.soinside.com 2019 - 2024. All rights reserved.