如何动态使用Python的类型提示来指示返回值与参数类型相同

mic*_*del 5 python typing type-hinting

我正在使用 Python 从磁盘读取 JSON,并且我试图确保我的类型提示在下游是正确的。例如,这样的事情:

from typing import List

def verify_contains_ints(items: List[object]) -> List[int]:
    for item in items:
        if not isinstance(item, int):
            raise TypeError("List contents must be all ints")
    return items
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我不想为 int、bool、str 等编写单独的函数。有没有办法动态指定我想要验证的类型?我想写的这样的:

from typing import List

def verify_contains_type(items: List[object], inner_type = object) -> List[inner_type]:
    for item in items:
        if not isinstance(item, inner_type):
            raise TypeError(f"List contents must be all {inner_type}s")
    return items
Run Code Online (Sandbox Code Playgroud)

在类型提示的当前状态下有没有办法做到这一点?

注意:这是我实际尝试做的事情的简化版本。默认的 inner_type 在这里可能看起来很愚蠢,但它对我的用例很重要。

jua*_*aga 4

我相信你可以typing.cast在这里使用,这有点难看。请注意,它没有运行时效果,它只是返回传递给它的内容,尽管它确实会产生函数调用开销。但它告诉类型检查器“现在是这种类型”。您应该使用 aTypeVar使其通用,然后像您试图做的那样简单地传递类型,并用Type

from typing import List, TypeVar, Type, cast

T = TypeVar('T')
def verify_contains_type(items: List[object], inner_type: Type[T]) -> List[T]:
    for item in items:
        if not isinstance(item, inner_type):
            raise TypeError("List contents must be all ints")
    return cast(List[T], items)


mylist: List[object] = [1, 2, 3, 4]

safe_mylist: List[int] = verify_contains_type(mylist, int)
print(safe_mylist[0] + safe_mylist[1])
Run Code Online (Sandbox Code Playgroud)

mypy 现在很高兴:

(py38) juan$ mypy --version
mypy 0.750
(py38) juan$ mypy test_typing.py
Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)