![](/img/trans.png)
[英]mypy complains: function type annotation with Type[TypeVar['T', str, date]] and T output: Incompatible return value type (got "str", expected "date")
[英]How to deal with "Incompatible return value type (got overloaded function)" issue
我正在尝试定义一个返回另一个函数的函数。 它返回的函数是重载的。
例如:
from typing import overload, Union, Callable
@overload
def foo(a: str) -> str:
pass
@overload
def foo(a: int) -> int:
pass
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
# str
return "one"
def bar() -> Callable[[Union[str, int]], Union[str, int]]:
return foo # Incompatible return value type (got overloaded function, expected "Callable[[Union[str, int]], Union[str, int]]")
但是,我在功能bar
输入是使用 Mypy 时出现的错误。
如何正确键入bar
? 我究竟做错了什么?
这里的问题部分在于Callable
类型有点过于受限,无法准确表达foo
的类型,部分在于 mypy 目前在分析与 Callables 重载的兼容性时非常保守。 (在一般情况下很难做到)。
目前最好的方法可能是通过使用回调协议定义更精确的返回类型并返回它:
例如:
from typing import overload, Union, Callable
# Or if you're using Python 3.8+, just 'from typing import Protocol'
from typing_extensions import Protocol
# A callback protocol encoding the exact signature you want to return
class FooLike(Protocol):
@overload
def __call__(self, a: str) -> str: ...
@overload
def __call__(self, a: int) -> int: ...
def __call__(self, a: Union[str, int]) -> Union[str, int]: ...
@overload
def foo(a: str) -> str:
pass
@overload
def foo(a: int) -> int:
pass
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
# str
return "one"
def bar() -> FooLike:
return foo # now type-checks
注意:从 Python 3.8 开始, Protocol
已添加到typing
模块中。 如果您希望在早期版本的 Python 中使用它,请安装typing_extensions module (
pip install typing_extensions`)并从那里导入它。
不得不像这样复制签名两次无疑有点笨拙。 人们似乎普遍同意这是一个问题(在打字和mypy问题跟踪器中有各种关于此的问题),但我认为对于如何最好地解决这个问题还没有达成任何共识。
我通过更改为 pyre 来解决这个问题:
from typing import overload, Union
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
return 'a string'
查看:
(.penv) nick$: pyre check
ƛ No type errors found
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.