【问题标题】:MyPy - "Incompatible types in assignment (expression has type None, variable has type ...)"MyPy - “赋值中的不兼容类型(表达式的类型为无,变量的类型......)”
【发布时间】:2023-03-10 20:09:01
【问题描述】:

我有以下函数,它给定一个'a-02/b-03/foobarbaz_c-04' 形式的字符串,将提取 abc。问题是,对于我的用例,输入字符串可能不包含 c,这样就没有要提取的数字了。

代码如下:

from typing import Tuple, Optional


def regex_a_b_c(name: str) -> Tuple[int, int, Optional[int]]:
        a_b_info = re.search('a-(\d\d)/b-(\d\d)/', name)
        a, b = [int(a_b_info.group(x)) for x in range(1, 3)]
        c_info = re.search('c-(\d\d)', name)
        if c_info:
            c = int(c_info.group(1))
        else:
            c = None   
        return a, b, c

我遇到的问题是,尽管我试图明确最后一个返回参数是 Optional[int],但我无法让我的 linter 停止抱怨变量 c。

我在c = None 行收到一条警告,上面写着:

赋值中不兼容的类型(表达式的类型为无,变量 具有 int 类型)

我该如何解决这个问题?

【问题讨论】:

    标签: python type-hinting mypy


    【解决方案1】:

    你应该返回一个元组 a,b,c 或一个元组 a,b 而不包括 c。这样,您根本不需要将值 None 分配给 c。

    if c_info:
        c = int(c_info.group(1))
        return a, b, c
    else:
        return a, b
    

    【讨论】:

    • 但这就是我将返回类型定义为Optional[int] 的原因。真的没有办法了吗?
    • 感谢您的更新。不幸的是,这不是最理想的,因为它不允许我在使用该函数时轻松解压缩结果。这就是为什么我想要一个 int、int、Optional[int] 的元组。
    • 嗯。您是否尝试将 c 声明为可选的 int,例如c: Optional[int] = None?
    【解决方案2】:

    如果您不注释变量,mypy 将根据它看到的第一个赋值 infer its type

    所以在这种情况下,c = int(_info.group(1)) 行首先出现,所以 mypy 决定类型必须是 int。然后,当它看到c = None 时,它随后会抱怨。

    解决此限制的一种方法是仅前向声明具有预期类型的​​变量。如果您使用的是 Python 3.6+ 并且可以使用变量注释,则可以这样做:

    c: Optional[int]
    if c_info:
        c = int(c_info.group(1))
    else:
        c = None
    

    或者更简洁,像这样:

    c: Optional[int] = None
    if c_info:
        c = int(c_info.group(1))
    

    如果您需要支持旧版本的 Python,您可以使用基于注释的语法对类型进行注释,如下所示:

    c = None  # type: Optional[int]
    if c_info:
        c = int(c_info.group(1))
    

    rje 的建议:

    if c_info:
        c = int(c_info.group(1))
        return a, b, c
    else:
        return a, b, None
    

    ...也是合理的。

    【讨论】:

      【解决方案3】:

      除了this answer 给出的好方法之外,我还遇到了另一种方法来让 mypy 忽略该行,方法是添加如下注释:

      c = None # type: ignore

      这似乎忽略了当前行的类型,但不影响使用变量的其他区域的类型推断。

      【讨论】:

      • 不知道为什么这被否决了,在我看来这是最好的答案:因为 mypy 是一个类型注释程序,它不应该导致你重组你的代码(所有其他答案都这样做)。谢谢:-)
      • 我投了反对票,因为这个 breaks 类型推断 - mypy 会将 c 视为具有类型 int 而不是类型 Optional[int],并将处理所有 @987654326 @ 操作在 c 上有效,即使 c 可能是 None
      • 我同意 Louis 的观点,目前这是最好的解决方案。老实说,这似乎是 MyPy 的一个缺点。仅仅因为它无法更新其推断类型,并不意味着我们应该重构为不那么可读/直观的东西。谢谢!
      猜你喜欢
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      相关资源
      最近更新 更多