Python 中是否有等同于 Typescript 的感叹号?

Is there an equivalent to Typescript's exlamantion point in Python?

我开始在 Python 中使用类型提示。我有以下功能:

def func(arg: Optional[str]):
    # ...
    # make sure arg is a string and not None
    do_something(arg)  # do_something expects a string

仅当 arg 确实是一个字符串而不是 None 时,才能调用 do_something,但 mypy 无法自行解决(这不是 mypy 的问题,它无法理解所有内容)。所以 mypy 标记对 do_something 的调用,因为 arg 可能是 None

在 Typescript 中,类似的情况可以用 arg! 处理——感叹号告诉静态分析器 arg 不是未定义的。 Python中有类似的东西吗?

python 中没有空安全。

你能做的最好的事情是:

if arg is not None:
    do_something(arg)

或者如果您想引发异常:

if arg is None:
    raise Exception("arg == none")

do_something(arg) # arg will not be None

此外,类型提示在正常情况下没有任何意义 python 因为这只是视觉上的,没有检查任何内容。例如,以下代码工作正常:

def x(y: int):
    return y

x("hello")

如果您的逻辑包含以下内容,Mypy 不应标记任何内容:

if arg is None:
    return None

如果那不可能,您也可以在警告前添加断言:

assert x is not None

TypeScript 和 Python 与 mypy 之间存在一些根本区别。它更接近 ECMAScript with Google Closure Compiler 的工作方式,而不是 TypeScript 的工作方式。或者,现代 IDE 如何在文档注释中使用类型提示。

首先,TypeScript 有一个类型系统和类型规则。 Python 没有 有类型系统或类型​​规则。 Python 只有 有类型提示的语法。但是,Python 本身不会对这些类型提示做任何事情。这留给第三方工具。这有一些优点和一些缺点。最大的优势是您可以选择对您的特定应用领域最有用的工具。最大的缺点是,当你写下类型提示时,你实际上并不知道它是什么意思……因为它没有任何意义。含义由外部第三方工具赋值。

换句话说:Python类型提示没有定义语义

第二个区别是 TypeScript 有一个单独的类型语言。 Python 的类型语言只是 Python。这意味着类型提示必须是语法上有效的 Python 表达式。事实上,类型提示是在运行时评估的,因此它们不仅必须在语法上有效 Python,它们还需要在语义上 有效 Python;它们需要可执行而没有错误或异常,即使您从未在运行时实际使用它们并且仅将它们用于静态类型检查,例如与我的。 (这是 typing 模块的主要原因:提供函数和对象,允许您将要编写的语法(例如泛型)转换为有效的运行时表达式。)

换句话说:Python类型提示没有单独的语法,它们只是Python表达式。

因此,这告诉我们的第一件事是,无论您提出什么潜在的解决方案,它都必须在句法和语义上有效 Python。 arg! 在语法上无效 Python。因此,完全等同于 TypeScript 语法是不可能的。

因此,我们必须检查是否可以找到具有不同语法的语义等价物。我们可能找到的地方是:

查看这三个,我们发现我们什么也没找到。这并不能证明这样的事情不存在(没有证据并不是不存在的证据),但这是一个很好的迹象。

Mypy 只支持相当于 TypeScript Type Guard:

if arg is None:
    pass
else:
    # mypy knows that `arg` is a `str` here

if arg is not None:
    # mypy knows that `arg` is a `str` here

if not arg:
    pass
else:
    # mypy knows that `arg` is a `str` here

if arg:
    # mypy knows that `arg` is a `str` here

如果你不能提供这样的类型保护,或者你绝对 100% 知道 arg 此时不能 成为 None,在任何情况下, EVER, 你可以提供一个类型断言:

assert arg is not None
# mypy knows that `arg` is a `str` here

类型断言也会让 mypy 知道 arg 不能是 None 之后。这在 mypy 文档中有明确记录。

这可能是语义上最接近 TypeScript ! 类型运算符的东西。事实上,! 运算符只是一个断言:“嘿,类型检查器,相信我,我知道一些你不知道的事情。” Python 断言也说了同样的话。