mypy 的“@overload”函数参数模式匹配中的案例穷举

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

我有一个Python类

MyClass
,有三种可接受的方法来实例化它:

  • 直接使用
    BitVector
    ;
  • 使用
    int
    bytes
    表示位向量的大小和内容;
  • 使用
    int
    str
    表示位向量的大小和内容。

使用类型注释,特别是

@overload
装饰器,我确保构造函数不会被滥用。 最重要的是,为了确保我不会忘记任何情况,我实现了详尽的模式匹配。

总而言之,它看起来如下:

from typing import overload, NoReturn, Optional, Union

def assert_never(value: NoReturn) -> NoReturn:
    assert False, f'Unhandled value: {value} ({type(value).__name__})'

class BitVector(): ...

class MyClass:

    @overload
    def __init__(self, *, size: int, content: bytes): ...
    @overload
    def __init__(self, *, size: int, content: int): ...
    @overload
    def __init__(self, *, bv: BitVector): ...

    def __init__(self, bv: Optional[BitVector]=None, size: Optional[int]=None, content: Optional[Union[bytes,int]]=None):
        if isinstance(size, int) and isinstance(content, (bytes, int)):
            # instanciate a BitVector and do something
            ...
        elif isinstance(bv, BitVector):
            # do something with it
            ...

        else:
            assert_never((bv, size, content))

但是,运行

mypy
时,出现以下错误:

example.py:25: error: Argument 1 to "assert_never" has incompatible type "Tuple[None, Optional[int], Union[bytes, int, None]]"; expected "NoReturn"
Found 1 error in 1 file (checked 1 source file)

就好像

mypy
仅依赖于实现函数的签名,而不考虑
@overload
声明的类型约束...

如何对参数可以采用的唯一类型组合(如

@overload
声明所声明的那样)执行详尽的模式匹配?

python pattern-matching overloading mypy python-typing
1个回答
-1
投票

您不应该向真正的 def 函数添加签名:

@overload
def __init__(self, *, size: int, content: Union[bytes, int]): ...

@overload
def __init__(self, *, bv: BitVector): ...

def __init__(self, *, bv=None, size=None , content=None):

我在真实的 def 中添加了 * 以遵循重载签名。

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