使用打字模块时如何检查类型兼容性?



我正在使用Python PEP484类型提示为我用Python编写的DSL编写类型检查器。如果我有一个函数,其中一个参数需要类型T,并且它被调用为S类型的表达式,我该如何检查调用是否有效?使用issubclass(S, T)就足够了吗?如果是这样,为什么mypy有如此复杂的is_subtype检查?还是我应该只使用mypy版本?

编辑:这里有一个例子来澄清我的意思。DSL有一个定义为:

T = TypeVar('T', float, str)
def op_add(operand1: T, operand2: T) -> T:
"Number addition or string concatenation."
# In this DSL, `+` cannot be used with lists
return operand1 + operand2  # Rely on Python overloading of `+`

然后,用户键入一个表达式,该表达式被解析为语法树,其分支可以是:node = OperatorNode('+', Literal([5.0]), Variable("abc"))。我们还不知道abc变量的值,但列表永远不能与+一起使用,所以我想提出一个TypeError来提醒用户。

如果我确实issubclass(typing.List[float], var),那会给我 False,所以我可以立即引发错误。我的问题是,当我构建DSL时,此检查是否可以保证跨案例工作,或者我是否需要使用更复杂的检查,例如mypy

如果两个要issubclass的参数都不包含来自typing模块的构造,如UnionCallableAny、泛型等,则issubclass检查就足够了。

typing构造作为其真实形式的影子存在于 python 运行时中,也就是说,它们不支持许多在概念上有意义的操作:

issubclass(List[int], List[int])  # runtimem error
issubclass(List[int], List) # True (as expected)
issubclass(str, Union[str]) # runtime error
issubclass(Union[str], str) # True (as expected)
issubclass(Union[int, str], str) # runtime error

有时issubclass可以使用typing结构,但一般来说,它可能会引发异常或给出不正确的答案;您需要根据具体情况弄清楚该怎么做。

mypy有一个更复杂的is_subtype,因为它确实需要处理所有typing结构,即使这样,仍然有一些工作要做。

最新更新