我试图完整地键入一个函数,确保元素在给定的字典中,然后检查元素类型是否符合用户的期望。我的初始实现工作正常,如下所示
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
,但如果元素类型为两种类型之一,例如 T
及 U
,返回值将为 T
或 U
.
我想这是可能的,但因为我还是一个新手在类型暗示领域,我需要一些帮助!
编辑:
我尝试使函数支持单个类型或两个不同类型的元组作为基本情况,因此我更新了 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"
1条答案
按热度按时间0x6upsns1#
你可以用
typing.overload
,它允许您为一个函数注册多个不同的签名。装饰有@overload
在运行时被python忽略,因此只需在函数体中添加省略号,就可以使函数体为空...
在身体里。这些实现只针对类型检查器-您必须确保至少有一个未使用重载修饰的函数“true”实现。然而,这感觉像是一个非常不完美的解决方案,因为它不能为传递给用户的任意长度的元组提供解决方案
element_type
论点只有当您知道元组的长度是(例如)2、3或4中的一个时,它才起作用——然后您可以为每种情况提供一个重载实现。如果有人能想出更好的解决方案,我肯定会感兴趣的。