具有两个用例的类型提示功能
Type hinting function with two use cases
我正在尝试对一个函数进行完整类型提示,以确保元素在给定字典中,然后检查元素类型是否符合用户的预期。我的初始实施工作正常,如下所示
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
,则 return 值是 T
,但如果 element_type 是其中之一,例如T
和 U
两种类型,return 值将是 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"
您可以使用typing.overload
,它允许您为一个函数注册多个不同的签名。用 @overload
修饰的函数在运行时会被 python 忽略,因此您可以通过在函数体中放置省略号 ...
将这些函数体留空。这些实现仅用于类型检查器——您必须确保至少有一个未用重载修饰的函数的“真实”实现。
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 之一时才有效——然后您可以为每种情况提供重载实现。如果有人能想到更好的解决方案,肯定会感兴趣。
我正在尝试对一个函数进行完整类型提示,以确保元素在给定字典中,然后检查元素类型是否符合用户的预期。我的初始实施工作正常,如下所示
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
,则 return 值是 T
,但如果 element_type 是其中之一,例如T
和 U
两种类型,return 值将是 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"
您可以使用typing.overload
,它允许您为一个函数注册多个不同的签名。用 @overload
修饰的函数在运行时会被 python 忽略,因此您可以通过在函数体中放置省略号 ...
将这些函数体留空。这些实现仅用于类型检查器——您必须确保至少有一个未用重载修饰的函数的“真实”实现。
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 之一时才有效——然后您可以为每种情况提供重载实现。如果有人能想到更好的解决方案,肯定会感兴趣。