[英]How to deal with "Incompatible return value type (got overloaded function)" issue
I'm trying to define a function which returns another function.我正在尝试定义一个返回另一个函数的函数。 The function it returns is overloaded.
它返回的函数是重载的。
For example:例如:
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]]")
However, my typing for the function bar
is coming up as an error using Mypy.但是,我在功能
bar
输入是使用 Mypy 时出现的错误。
How do I type bar
correctly?如何正确键入
bar
? What am I doing wrong?我究竟做错了什么?
The issue here is partly that the Callable
type is a little too limited to accurately express the type for foo
and also partly that mypy is currently very conservative when analyzing the compatibility of overloads against Callables.这里的问题部分在于
Callable
类型有点过于受限,无法准确表达foo
的类型,部分在于 mypy 目前在分析与 Callables 重载的兼容性时非常保守。 (It's hard to do in the general case). (在一般情况下很难做到)。
Probably the best approach for now is to just define a more precise return type by using Callback protocol and return that instead:目前最好的方法可能是通过使用回调协议定义更精确的返回类型并返回它:
For example:例如:
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
Note: Protocol
was added to the typing
module as of Python 3.8.注意:从 Python 3.8 开始,
Protocol
已添加到typing
模块中。 If you want it in earlier versions of Python, install the typing_extensions module (
pip install typing_extensions`) and import it from there.如果您希望在早期版本的 Python 中使用它,请安装
typing_extensions module (
pip install typing_extensions`)并从那里导入它。
Having to copy the signature like this twice is admittedly a bit clunky.不得不像这样复制签名两次无疑有点笨拙。 People generally seem to agree that this is a problem (there are various issues about this in the typing and mypy issue trackers), but I don't think there's any consensus on how to best solve this yet.
人们似乎普遍同意这是一个问题(在打字和mypy问题跟踪器中有各种关于此的问题),但我认为对于如何最好地解决这个问题还没有达成任何共识。
I sorted that out by changing to pyre:我通过更改为 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'
check:查看:
(.penv) nick$: pyre check
ƛ No type errors found
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.