MyPy - “赋值中不兼容的类型(表达式类型为”无“,变量类型为”...)”

MyPy - "Incompatible types in assignment (expression has type None, variable has type ...)"

提问人:Daniel 提问时间:10/16/2018 最后编辑:Martijn PietersDaniel 更新时间:7/25/2022 访问量:29982

问:

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

代码如下:

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

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

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

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

我该如何解决这个问题?

python 类型提示 mypy

评论


答:

2赞 rje 10/16/2018 #1

应返回元组或不包括 c 的元组。这样,您根本不需要将值 None 分配给 c。a,b,ca,b

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

评论

0赞 Daniel 10/16/2018
但这就是为什么我将返回类型定义为具有 .真的没有办法吗?Optional[int]
0赞 Daniel 10/16/2018
感谢您的更新。不幸的是,这是次优的,因为它不允许我在使用该函数时轻松解压缩结果。这就是为什么我想要一个 int、int、Optional[int] 的元组。
0赞 rje 10/16/2018
嗯。您是否尝试将 c 声明为可选的 int,例如?c: Optional[int] = None
35赞 Michael0x2a 10/18/2018 #2

如果你不给变量注解,mypy 会根据它看到的第一个赋值来推断它的类型

因此,在本例中,该行首先出现,因此 mypy 决定类型必须为 。然后,当它看到 .c = int(_info.group(1))intc = 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

...也是一个合理的。

7赞 krumpelstiltskin 5/13/2021 #3

除了这个答案给出的好方法之外,我还遇到了另一种方法,通过添加如下评论来让 mypy 忽略该行:

c = None    # type: ignore

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

评论

8赞 Louis Maddox 7/10/2021
不知道为什么这被否决了,在我看来这是最好的答案:因为 mypy 是一个类型注释程序,它不应该导致你重构你的代码(所有其他答案都会这样做)。谢谢 :-)
0赞 user2357112 11/3/2021
我投了反对票,因为这破坏了类型推断 - mypy 将被视为具有类型而不是类型,并将所有操作视为有效,即使可能是。cintOptional[int]intccNone
0赞 Zach 11/3/2021
我同意路易斯的观点,目前这是最好的解决方案。老实说,这似乎是MyPy的缺点。仅仅因为它无法更新其推断类型,并不意味着我们应该重构为可读性/直观性较差的东西。谢谢!