在构建Python库时,我使用类型提示来保证某些数据表示的一致性。特别是,我以嵌套方式使用Union
(总和类型)来表示数据可以采用的不同“风格”
到目前为止,我得到的结果与以下示例类似:
from typing import Union
MyNumberT = Union[float,int]
MyDataT = Union[str,MyNumber]
def my_data_to_string(datum: MyDataT) -> str:
if isinstance(datum, float):
return _my_number_to_string(datum)
elif isinstance(datum, int):
return _my_number_to_string(datum)
elif isinstance(datum, str):
return datum
# assert_never omitted for simplicity
def _my_number_to_string(number: MyNumberT) -> str:
return "%s" % number
哪种类型使用mypy
检查良好
现在,我的实际代码有点复杂,我需要对MyNumberT
类型的变量执行一些常见的操作。
在本例中,通过调整import
并替换my_data_to_string
来强调这一点,如下所示:
from typing import get_args, Union
[...]
def my_data_to_string(datum: MyDataT) -> str:
if isinstance(datum, get_args(MyNumberT)):
return _my_number_to_string(datum)
elif isinstance(datum, str):
return datum
# assert_never omitted for simplicity
[...]
在其上mypy
的类型检查失败:
Argument 1 to "_my_number_to_string" has incompatible type "Union[str, Union[float, int]]"; expected "Union[float, int]"
我希望mypy
能够“意识到”在第一个分支中,datum
只能是float
或int
类型,但错误消息表明情况并非如此
如何在这种嵌套类型的“部分”上实现一些模式匹配
您的用例是使用
functools
提供的名为singledispatch
的实用程序的一个很好的例子。它允许您根据输入类型将多个功能定义为单个功能它是可扩展的、可读的,并且不会在linter/formatters中生成错误Docs link
从Python 3.10开始,unions are valid for isinstance checks:
只要足以排除工会的一个组成部分,无需要求即可撤销检查工作:
请注意,这使用了
else
而不是elif
子句–依赖类型检查器拒绝类型错误的参数对于更复杂的类型,可以构建类型保护:
这告诉类型检查器,它将返回所需的已包装类型,或者返回错误的内容。
type: ignore
是必需的,因为它使用相同的类型检查实现;该函数用作围绕不支持的运行时检查添加有效的静态类型检查它可以通过赋值表达式和解包来使用:
相关问题 更多 >
编程相关推荐