python-3.x - 带有异常处理的 Python 类型

标签 python-3.x exception type-hinting mypy

以下代码存储在名为 sample.py 的文件中。

import re
from typing import Optional, Tuple
 
def func(path: str) -> Optional[Tuple[str, str]]:
    regex = re.compile(r"/'([^/']+?)'/'([^/']+?)'")
    try:
        return regex.match(path).groups()
    except AttributeError:
        return None

Mypy Python linter 在分析代码时抛出以下错误:

sample.py:8: error: Incompatible return value type (got "Union[Sequence[str], Any]", expected "Optional[Tuple[str, str]]")
sample.py:8: error: Item "None" of "Optional[Match[str]]" has no attribute "groups"

虽然 regex.match(path).groups()可能会返回 None类型,它没有 groups属性,处理结果异常并在返回类型中指定处理。但是,Mypy 似乎不明白正在处理异常。据我了解 Optional[Tuple[str, str]]是正确的返回类型,而 Mypy 坚持使用不太具体的类型 Union[Sequence[str], Any]是正确的 。在 Python 类型中使用异常处理的正确方法是什么? (请注意,我并不是要求在不使用异常处理的情况下编写代码的替代方法。我只是想提供一个最小且完整的示例,其中 Python 类型检查器的行为与我期望的异常处理不同。)

最佳答案

Mypy 并没有真正理解深层的异常——在这种情况下,它不理解因为你捕获了 AttributeError,它可以忽略“如果 regex.match(path) 是 None 会怎么样?”案件。

更一般地说,mypy 所做的基本假设是,当您有一些对象时 foo带类型 Union[A, B]你做 foo.bar() , 两种类型 AB有一个 bar()方法。

如果这些类型中只有一种具有 bar()方法,您需要执行以下操作之一:

  • 在执行属性访问之前,为 mypy 提供足够的信息以将联合范围缩小到相关类型之一。例如,isinstance 检查,x is not None检查...
  • 承认您正在尝试做一些类型检查器不理解的事情,并满足于抑制生成的错误。例如,您可以强制转换类型,添加 # type: ignore评论,想办法制作foo成为动态 Any类型...
  • 找到一种重新设计代码的方法来完全回避这个问题。

  • (在这种特殊情况下,我认为另一种选择可能是向 mypy 提交拉取请求以添加对这种模式的支持。但我不确定这是否真的可行:改变任何类型的基本假设在多个维度上都是困难的工作。 )

    同样,Mypy 也不理解深层的正则表达式——例如不会尝试分析您的正则表达式以确定您将获得多少组,因此不会理解您的特定正则表达式恰好将字符串与两个组匹配。它可以做的最好的事情是断言该组将返回一些未知数量的字符串——因此类型 Sequence[str]而不是 Tuple[str, str] .

    这种限制通常在类型检查器中很常见,实际上:主流语言中的大多数类型系统并不真正支持基于传入的任何实际值的内容来断言返回类型的方法。这种类型系统(依赖类型系统、细化类型系统......)实现起来非常困难,并且对于最终用户来说通常有一个陡峭的学习曲线。

    但是,通过编写 mypy plugin 使 mypy 尽最大努力支持这一点会更容易。 ,如果你愿意的话。具体来说,试试看 get_method_hook()get_function_hook() .

    关于python-3.x - 带有异常处理的 Python 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57118995/

    相关文章:

    python - 如何创建python迭代器的副本?

    c++ - 在 catch block 中重新抛出异常

    python - 用于 python 类型提示检查的控制台工具

    python - 使用 csv 阅读器后无法使用

    python - 从 Python 3 中的文件读取行时如何更改默认换行符?

    android - 为什么在使用 min3d 框架加载 3d 模型时出现 "android.content.res.Resources$NotFoundException: Resource ID #0x0"?

    php - 是否有匹配 "string"和 "Object that implements __toString()"的 native 接口(interface)?

    php - 类变量中的类型提示

    python - Matplotlib 范围与 mollweide 投影

    c - 使用strncpy复制字符串时遇到异常