如何使用多个可选参数对函数进行类型重载?
How to type-overload functions with multiple optional args?
我有一个带有多个默认值的 kwargs 的函数。其中之一(在中间某处)是控制 return 类型的布尔切换。
我想使用 Literal[True/False]
为此方法创建两个重载,但保留默认值。
我的想法如下:
from typing import overload, Literal
@overload
def x(a: int = 5, t: Literal[True] = True, b: int = 5) -> int: ...
@overload
def x(a: int = 5, t: Literal[False] = False, b: int = 5) -> str: ...
def x(a: int = 5, t: bool = True, b: int = 5) -> int | str:
if t:
return 5
return "asd"
但是 mypy 提出:
error: Overloaded function signatures 1 and 2 overlap with incompatible return types
我认为这是因为 x()
会发生冲突。
但是我无法删除第二个重载中的默认 = False
值,因为它前面是带有默认值的 arg a
。
我怎样才能正确地重载这个
x()
→int
x(t=True)
→int
x(t=False)
→str
老问题了。原因是您在两个分支中都指定了默认值,因此 x()
在两个分支中都是可能的,并且 return 类型未定义。
对于这种情况,我有以下模式:
from typing import overload, Literal
@overload
def x(a: int = 5, t: Literal[True] = True, b: int = 5) -> int: ...
@overload
def x(a: int = 5, *, t: Literal[False], b: int = 5) -> str: ...
@overload
def x(a: int, t: Literal[False], b: int = 5) -> str: ...
def x(a: int = 5, t: bool = True, b: int = 5) -> int | str:
if t:
return 5
return "asd"
为什么以及如何?您必须考虑调用函数的方法。首先,您可以提供 a
,然后 t
可以作为 kwarg (#2) 或 arg (#3) 给出。您也可以保留 a
默认值,然后 t
始终是一个 kwarg(又是#2)。这是为了防止将 arg 放在 kwarg 之后,即 SyntaxError
。重载多个参数比较困难,但也可以这样:
@overload
def f(a: int = 1, b: Literal[True] = True, c: Literal[True] = True) -> int: ...
@overload
def f(a: int = 1, *, b: Literal[False], c: Literal[True] = True) -> Literal['True']: ...
@overload
def f(a: int = 1, *, b: Literal[False], c: Literal[False]) -> Literal['False']: ...
@overload
def f(a: int, b: Literal[False], c: Literal[True] = True) -> Literal['True']: ...
@overload
def f(a: int, b: Literal[False], c: Literal[False]) -> Literal['False']: ...
def f(a: int = 1, b: bool = True, c: bool = True) -> int | Literal['True', 'False']:
return a if b else ('True' if c else 'False') # mypy doesn't like str(c)
你可以玩重载here。
我有一个带有多个默认值的 kwargs 的函数。其中之一(在中间某处)是控制 return 类型的布尔切换。
我想使用 Literal[True/False]
为此方法创建两个重载,但保留默认值。
我的想法如下:
from typing import overload, Literal
@overload
def x(a: int = 5, t: Literal[True] = True, b: int = 5) -> int: ...
@overload
def x(a: int = 5, t: Literal[False] = False, b: int = 5) -> str: ...
def x(a: int = 5, t: bool = True, b: int = 5) -> int | str:
if t:
return 5
return "asd"
但是 mypy 提出:
error: Overloaded function signatures 1 and 2 overlap with incompatible return types
我认为这是因为 x()
会发生冲突。
但是我无法删除第二个重载中的默认 = False
值,因为它前面是带有默认值的 arg a
。
我怎样才能正确地重载这个
x()
→int
x(t=True)
→int
x(t=False)
→str
老问题了。原因是您在两个分支中都指定了默认值,因此 x()
在两个分支中都是可能的,并且 return 类型未定义。
对于这种情况,我有以下模式:
from typing import overload, Literal
@overload
def x(a: int = 5, t: Literal[True] = True, b: int = 5) -> int: ...
@overload
def x(a: int = 5, *, t: Literal[False], b: int = 5) -> str: ...
@overload
def x(a: int, t: Literal[False], b: int = 5) -> str: ...
def x(a: int = 5, t: bool = True, b: int = 5) -> int | str:
if t:
return 5
return "asd"
为什么以及如何?您必须考虑调用函数的方法。首先,您可以提供 a
,然后 t
可以作为 kwarg (#2) 或 arg (#3) 给出。您也可以保留 a
默认值,然后 t
始终是一个 kwarg(又是#2)。这是为了防止将 arg 放在 kwarg 之后,即 SyntaxError
。重载多个参数比较困难,但也可以这样:
@overload
def f(a: int = 1, b: Literal[True] = True, c: Literal[True] = True) -> int: ...
@overload
def f(a: int = 1, *, b: Literal[False], c: Literal[True] = True) -> Literal['True']: ...
@overload
def f(a: int = 1, *, b: Literal[False], c: Literal[False]) -> Literal['False']: ...
@overload
def f(a: int, b: Literal[False], c: Literal[True] = True) -> Literal['True']: ...
@overload
def f(a: int, b: Literal[False], c: Literal[False]) -> Literal['False']: ...
def f(a: int = 1, b: bool = True, c: bool = True) -> int | Literal['True', 'False']:
return a if b else ('True' if c else 'False') # mypy doesn't like str(c)
你可以玩重载here。