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

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

我有以下函数,它给出了

'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
行收到一条警告,上面写着:

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

我该如何解决这个问题?

python type-hinting mypy
4个回答
36
投票

如果您不注释变量,mypy 将根据它看到的第一个赋值推断其类型

所以在这种情况下,

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

...也是合理的。


9
投票

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

c = None    # type: ignore

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


2
投票

您应该返回一个元组

a,b,c
或一个元组
a,b
而不包含 c。这样您根本不需要为 c 分配 None 值。

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

0
投票

尝试使用|符号

def regex_a_b_c(name: str) -> tuple[int, int, int | None]:
© www.soinside.com 2019 - 2024. All rights reserved.