python - 向 JSON 对象 Hook 添加类型提示的正确方法

标签 python mypy python-typing

json module docs 中的示例为例:

>>> def as_complex(dct):
...     if '__complex__' in dct:
...         return complex(dct['real'], dct['imag'])
...     return dct

在这里添加类型提示的正确方法是什么?我使用 TypedDict 和重载的天真方法失败了:

from typing import Any, Dict, TypedDict, TypeVar, Union, overload


_T = TypeVar('_T', bound=Dict[str, Any])


class JSONDict(TypedDict):
    __complex__: Any
    real: float
    imag: float


@overload
def as_complex(dct: JSONDict) -> complex: ...
@overload
def as_complex(dct: _T) -> _T: ...


def as_complex(dct: _T) -> Union[complex, _T]:
    if '__complex__' in dct:
        return complex(dct['real'], dct['imag'])
    return dct

作为 mypy 对象:

main.py:14: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
main.py:19: error: Overloaded function implementation cannot satisfy signature 1 due to inconsistencies in how they use type variables

Playground gist , 如果您想在浏览器中试用示例。

最佳答案

显然 mypyJSONDict_T 视为重叠类型,很可能是由于 AnyTypeVar 定义。 这让我想起了以下情况(只是示例):

class A: ...
class B: ...
class C: ...
class D: ...

@overload
def f(x: Union[A, B]) -> int: ...  # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Union[B, C]) -> str: ...
def f(x): ...

我们可以让它们重叠或尝试将它们分开。目前,我可以提出两个相当丑陋的解决方案。

from typing import Any, Dict, TypedDict, TypeVar, Union, overload, cast


_T = TypeVar('_T', bound=Dict[str, Any])


class JSONDict(TypedDict):
    __complex__: Any
    real: float
    imag: float


@overload
def as_complex(dct: JSONDict) -> complex: ...
@overload
def as_complex(dct: _T) -> Union[_T, complex]: ...


def as_complex(dct: Union[_T, JSONDict]) -> Union[complex, _T]:
    if '__complex__' in dct:
        return complex(dct['real'], dct['imag'])
    return cast(_T, dct)

或者尝试分开

from typing import Any, Dict, TypedDict, TypeVar, Union, overload, cast

# narrowing the list of types excluding float
_T = TypeVar('_T', bound=Dict[str, Union[int, str, list, tuple, dict, set]])  
 

class JSONDict(TypedDict):
    __complex__: Any
    real: float
    imag: float


@overload
def as_complex(dct: JSONDict) -> complex: ...
@overload
def as_complex(dct: _T) -> _T: ...


def as_complex(dct: Union[_T, JSONDict]) -> Union[complex, _T]:
    if '__complex__' in dct:
        dct = cast(JSONDict, dct)
        return complex(dct['real'], dct['imag'])
    return cast(_T, dct)

希望有人能提出更优雅的解决方案

关于python - 向 JSON 对象 Hook 添加类型提示的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63331368/

相关文章:

python - python中的Lambda参数函数

python-3.x - 如何让 mypy 提示将 Any 分配给 int(第 2 部分)

python-3.x - 绑定(bind)方法的 MyPy 类型注释?

python-3.x - 从可调用类型签名中删除 Self 以匹配实例方法

python - 使用 TypeVar 作为 Callable 的参数时出现问题

python - 尝试从 ubuntu crontab 运行 python 脚本

python - 用 python 制作一个(希望简单的)wiki 解析器

python - Pandas:使用重复值进行透视

python-3.x - Python 键入 : Create a class function with a generic type, 并通过类访问该类型

python - 为什么当mypy需要类型注解时,stupid annotation会处理错误?