python类型的提示函数,有两个用例

tf7tbtn2  于 2021-09-08  发布在  Java
关注(0)|答案(1)|浏览(230)

我试图完整地键入一个函数,确保元素在给定的字典中,然后检查元素类型是否符合用户的期望。我的初始实现工作正常,如下所示

T = TypeVar("T")

def check_and_validate_element_in_dict(
    element_name: str, dictionary: Dict[str, Any], element_type: Type[T]
) -> T:
    assert element_name in dictionary
    element = dictionary[element_name]
    assert isinstance(element, element_type)
    return element

它允许我替换这个

assert "key1" in _dict
key1 = _dict["key1"]
assert isinstance(key1, type1)

assert "key2" in _dict
key2 = _dict["key2"]
assert isinstance(key2, type2)

用这个

key1 = check_and_validate_element_in_dict("key1", _dict, type1)
key2 = check_and_validate_element_in_dict("key2", _dict, type2)

现在,这只在要测试的元素类型只有一个时起作用,如 int , str 我还希望能够在我的函数中测试多个不同的类型,比如

isinstance(element, (int, dict))
isinstance(element, (float, type(None)))

这里的问题是类型暗示函数,以便让它理解如果 element_type 是一个单一的值 T ,返回值为 T ,但如果元素类型为两种类型之一,例如 TU ,返回值将为 TU .
我想这是可能的,但因为我还是一个新手在类型暗示领域,我需要一些帮助!
编辑:
我尝试使函数支持单个类型或两个不同类型的元组作为基本情况,因此我更新了 element_type 成为

element_type: Union[Type[T], Tuple[Type[T], Type[T]]]

现在 return element 语句被标记为 mypy 错误如下:

Returning Any from function declared to return "T"

这也提出了一个问题:我是否需要将每个不同的输入类型表示为一个新的输入类型 TypeVar ? 在这种情况下 element_type 定义变得


# using U = TypeVar("U")

def ...(..., element_type: Union[Type[T], Tuple[Type[T], Type[U]]]) -> Union[T, U]:

在这种情况下,问题一直存在

Returning Any from function declared to return "T"
0x6upsns

0x6upsns1#

你可以用 typing.overload ,它允许您为一个函数注册多个不同的签名。装饰有 @overload 在运行时被python忽略,因此只需在函数体中添加省略号,就可以使函数体为空 ... 在身体里。这些实现只针对类型检查器-您必须确保至少有一个未使用重载修饰的函数“true”实现。

from typing import TypeVar, overload, Any, Union, Dict, Type, Tuple

t0 = TypeVar('t0')
t1 = TypeVar('t1')

@overload
def check_and_validate_element_in_dict(
        element_name: str,
        dictionary: Dict[str, Any],
        element_type: Type[t0]
) -> t0:
    """
    Signature of the function if exactly one type
    is supplied to argument element_type
    """
    ...

@overload
def check_and_validate_element_in_dict(
        element_name: str,
        dictionary: Dict[str, Any],
        element_type: Tuple[Type[t0], Type[t1]]
) -> Union[t0, t1]:
    """
    Signature of the function if a tuple of exactly two types
    is supplied to argument element_type
    """     
    ...

def check_and_validate_element_in_dict(
        element_name: str,
        dictionary: Dict[str, Any],
        element_type: Any
) -> Any:
    """Concrete implementation of the function"""

    assert element_name in dictionary
    element = dictionary[element_name]
    assert isinstance(element, element_type)
    return element

然而,这感觉像是一个非常不完美的解决方案,因为它不能为传递给用户的任意长度的元组提供解决方案 element_type 论点只有当您知道元组的长度是(例如)2、3或4中的一个时,它才起作用——然后您可以为每种情况提供一个重载实现。如果有人能想出更好的解决方案,我肯定会感兴趣的。

相关问题