我正在尝试使用 重载 使可变参数函数的返回类型以某种方式取决于其参数的类型。具体来说,当且仅当其参数的any是X类型时,我希望返回类型为X。
考虑以下最小示例:
from typing import overload
class Safe:
pass
class Dangerous:
pass
@overload
def combine(*args: Safe) -> Safe: ...
@overload
def combine(*args: Safe | Dangerous) -> Safe | Dangerous: ...
def combine(*args: Safe | Dangerous) -> Safe | Dangerous:
if all(isinstance(arg, Safe) for arg in args):
return Safe()
else:
return Dangerous()
reveal_type(combine())
reveal_type(combine(Safe()))
reveal_type(combine(Dangerous()))
reveal_type(combine(Safe(), Safe()))
reveal_type(combine(Safe(), Dangerous()))
这输出
example.py:21: note: Revealed type is "example.Safe"
example.py:22: note: Revealed type is "example.Safe"
example.py:23: note: Revealed type is "Union[example.Safe, example.Dangerous]"
example.py:24: note: Revealed type is "example.Safe"
example.py:25: note: Revealed type is "Union[example.Safe, example.Dangerous]"
Success: no issues found in 1 source file
我想设置一些东西,例如,
combine(Dangerous())
和 combine(Safe(), Dangerous())
的推断类型是 Dangerous
而不是 Safe | Dangerous
。将第二个重载的返回类型更改为 Dangerous
会产生错误:
example.py:10: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]
example.py:21: note: Revealed type is "example.Safe"
example.py:22: note: Revealed type is "example.Safe"
example.py:23: note: Revealed type is "example.Dangerous"
example.py:24: note: Revealed type is "example.Safe"
example.py:25: note: Revealed type is "example.Dangerous"
Found 1 error in 1 file (checked 1 source file)
因此,我似乎需要一种方法来注释第二个重载以明确声明至少一个它的参数是
Dangerous
。有没有办法做到这一点?
使用 PyRight,您的解决方案确实有效。而mypy也可以用简单的方式强行接受
# type: ignore
:
@overload
def combine(*args: Safe) -> Safe: ... # type: ignore
@overload
def combine(*args: Safe | Dangerous) -> Dangerous: ...
def combine(*args: Safe | Dangerous) -> Safe | Dangerous:
if all(isinstance(arg, Safe) for arg in args):
return Safe()
else:
return Dangerous()
reveal_type(combine()) # Safe
reveal_type(combine(Safe())) # Safe
reveal_type(combine(Dangerous())) # Dangerous
reveal_type(combine(Safe(), Safe())) # Safe
reveal_type(combine(Safe(), Dangerous())) # Dangerous