我必须使用不同大小的参数重载 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)
我能够通过使用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)