python - 如何处理 "Incompatible return value type (got overloaded function)"问题

标签 python python-3.x type-hinting mypy

我正在尝试定义一个返回另一个函数的函数。它返回的函数已重载。

例如:

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]]")

但是,我使用 Mypy 输入函数 bar 时出现错误。

如何正确输入 bar?我做错了什么?

最佳答案

这里的问题部分是因为 Callable 类型有点太有限,无法准确表达 foo 的类型,还有部分是 mypy 目前在分析重载与 Callables 的兼容性。 (一般情况下很难做到)。

目前最好的方法可能是使用 Callback protocol 定义更精确的返回类型。并返回:

例如:

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 模块 (pip install Typing_extensions`) 并从那里导入它。

不得不像这样复制签名两次确实有点笨拙。人们似乎普遍认为这是一个问题(typingmypy 问题跟踪器中有关于此问题的各种问题),但我认为对于如何最好地解决这个问题还没有达成共识。

关于python - 如何处理 "Incompatible return value type (got overloaded function)"问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56624854/

相关文章:

python - 如何在 python 中使用 wordpress REST api 上传图像?

python - to_excel() 没有索引布局

python - "Unsupported target for indexed assignment"与 mypy,取决于与分配有关的类型提示时刻

python 键入模块在 python 3.5 中缺少 Coroutine 类

python - Django MySQL 查询 - 选择比上一行大 60 分钟的日期时间?

Python preference finder——如何实现二进制插入排序

python - 根据 Pandas 数据框中的键列减去列

python-3.x - 使用 VB.Net 通过 TCP 发送文件并使用 Python3.6 中的 Socket 接收时出现文件编码错误

clojure - 使用包含类型提示的宏生成Clojure代码

python - 使用 alembic 自动生成迁移