分配mypy中的类型不兼容

dan*_*gom 2 python typing mypy

我有以下函数,给定形式的字符串'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
Run Code Online (Sandbox Code Playgroud)

我的问题是,尽管试图弄清楚最后一个返回参数是an Optional[int],但我还是不能让我的小子停止抱怨变量c。

我收到警告c =None

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

。我该如何解决这个问题?

kru*_*kin 8

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

c = None    # type: ignore
Run Code Online (Sandbox Code Playgroud)

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

  • 不知道为什么这被否决了,在我看来这是最好的答案:因为 mypy 是一个类型注释程序,所以它不应该导致您重组代码(所有其他答案都会这样做)。谢谢 :-) (9认同)

Mic*_*x2a 5

首次使用变量时,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
Run Code Online (Sandbox Code Playgroud)

或更简洁地说,像这样:

c: Optional[int] = None
if c_info:
    c = int(c_info.group(1))
Run Code Online (Sandbox Code Playgroud)

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

c = None  # type: Optional[int]
if c_info:
    c = int(c_info.group(1))
Run Code Online (Sandbox Code Playgroud)

rje的建议:

if c_info:
    c = int(c_info.group(1))
    return a, b, c
else:
    return a, b, None
Run Code Online (Sandbox Code Playgroud)

...也是一个合理的选择。