Mypy with --disallow-untyped-defs忽略@overload?

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

我正在考虑在mypy github上打开错误报告,但我想确保自己不只是愚蠢。我使用disallow-untyped-defs选项运行mypy。当我使用@overload注释函数类型并在定义中省略注释时,mypy仍然会产生错误。对我来说,该功能似乎应该被注释。

example.py:

from typing import overload
@overload
def f(arg: int) -> int: ...
@overload
def f(arg: str) -> str: ...

def f(arg):
    if type(arg) == int:
        return 1
    elif type(arg) == str:
        return "a"
    else:
        raise ValueError

命令行:

mypy --disallow-untyped-defs example.py

输出:

example.py:7: error: Function is missing a type annotation
Found 1 error in 1 file (checked 1 source file)
mypy
1个回答
0
投票

这是预期的行为。 Mypy希望您将类型注释添加到重载的实现中,例如:

from typing import overload, Union

@overload
def f(arg: int) -> int: ...
@overload
def f(arg: str) -> str: ...
def f(arg: Union[int, str]) -> Union[int, str]:
    if type(arg) == int:
        return 1
    elif type(arg) == str:
        return "a"
    else:
        raise ValueError

这样,mypy仍将具有成功键入检查f的正文所需的所有信息。

mypy不会基于重载类型签名自动推断实现类型签名,或尝试使用重载签名两次尝试对实现进行类型检查的原因是,这两个签名通常最终会彼此非常不同。

例如,这是一个更复杂的重载示例:

@overload
def zip(/, i1: Iterable[_T1]) -> Iterator[Tuple[_T1]]: ...
@overload
def zip(/, i1: Iterable[_T1], i2: Iterable[_T2]) -> Iterator[Tuple[_T1, _T2]]: ...
@overload
def zip(/, i1: Iterable[_T1], i2: Iterable[_T2],
        i3: Iterable[_T3]) -> Iterator[Tuple[_T1, _T2, _T3]]: ...
@overload
def zip(/, i1: Iterable[_T1], i2: Iterable[_T2], i3: Iterable[_T3],
        i4: Iterable[_T4]) -> Iterator[Tuple[_T1, _T2, _T3, _T4]]: ...
@overload
def zip(/, i1: Iterable[_T1], i2: Iterable[_T2], i3: Iterable[_T3],
        i4: Iterable[_T4], i5: Iterable[_T5]) -> Iterator[Tuple[_T1, _T2, _T3, _T4, _T5]]: ...
@overload
def zip(/, i1: Iterable[Any], i2: Iterable[Any], i3: Iterable[Any],
        i4: Iterable[Any], i5: Iterable[Any], i6: Iterable[Any],
        *remainder: Iterable[Any]) -> Iterator[Tuple[Any, ...]]: ...
def zip(*iterables: Iterable[Any]) -> Iterator[Tuple[Any, ...]]:
    sentinel = object()
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            elem = next(it, sentinel)
            if elem is sentinel:
                return
            result.append(elem)
        yield tuple(result)

mypy推断在这个示例中确切应该是什么实现签名非常具有挑战性:参数数量不匹配,弄清楚所有TypeVar怎么处理(保留它们?丢弃它们?)很棘手...

这些都是mypy从理论上可以解决的问题,但是从长远来看,它是否真的为用户节省了这么多时间,目前尚不清楚。在像这样的复杂情况下,用户实际上可能更希望能够说明实现签名的确切含义。

((如果问题是(a)困难而(b)是小问题,则它往往无法解决,尤其是在开源项目中。)

因此,为了保持一致的体验,mypy不会在每种情况下都尝试自动推断实现签名。

© www.soinside.com 2019 - 2024. All rights reserved.