如何使用 mypy 检查过载的单次调度

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

我必须使用不同大小的参数重载 python 函数。我可以做到,并且可以对不正确的调用进行运行时检查,请参见下文。是否可以让 mypy 检查错误用法? 我正在使用 python-3.7.3 和 mypy-0.770。

from functools import singledispatch

class A:
    def __init__(self) -> None:
        self.dummy = 0

class B:
    def __init__(self) -> None:
        self.dummy = 1


@singledispatch
def base(arg, *args) -> None:
    del arg, args # Not used
    # It should not be called
    print("unexpected call to dummy base")

@base.register
def xa(arg: A, val0: int, sval: str="") -> None:
    del arg # Not used
    if not isinstance(sval, str) :
        print("bad call to a-variant")
        return
        
        
    print("called a-variant: val0={} sval='{}' ".format(val0, sval))

@base.register
def xb(arg: B, val0: int, val1: int, sval: str ="") -> None:
    del arg # Not used
    print("called b-variant: val0={} val1={} sval='{}'".format(val0, val1, sval))

def test() -> None:
    base(A(), 10)
    base(A(), 11, "xxx")
    base(B(), 10, 20)
    base(B(), 11, 22, "yyy")

    # Bad
    base(A(), 10, 20)

python python-typing mypy
1个回答
2
投票

我能够通过使用typing.overload解决这个问题。

更新:花了一些时间来解决重载函数不接受所有可能的参数的 mypy 错误。

from typing import overload, Optional, Union

class A:
    def __init__(self) -> None:
        self.dummy = 0

class B:
    def __init__(self) -> None:
        self.dummy = 1


@overload
def base(arg: A, val0: int, val1: str = "") -> None:
    ...

@overload
def base(arg: B, val0: int, val1: int, val2:str = "") -> None:
    ...


def base(arg: Union[A, B], val0: int, val1: Union[str, int] = "", val2: Optional[str] = None) -> None:
    if isinstance(arg, A):
        print("got A")
        return

    if isinstance(arg, B):
        print("got B")
        return

    print("unexpected")


def test() -> None:
    base(A(), 10, "xxx")
    base(B(), 10, 20, "yyy")

    # Bad
    base(A(), "xxx", 10, 20)
    base(B(), "xxx", 10, "ttt")
    base(25)
© www.soinside.com 2019 - 2024. All rights reserved.