为了更好地理解泛型容器类型暗示的工作原理,我研究了^{MutableMapping
类定义中发现了以下几行:
@overload
def pop(self, k: _KT) -> _VT: ...
@overload
def pop(self, k: _KT, default: Union[_VT, _T] = ...) -> Union[_VT, _T]: ...
{do{cd3>的附加参数是这个部分的。只能为MutableMapping
指定两个参数:_KT
和{_T
参数仍然未指定。类型检查器如何解决第三种类型。。。?在
我本来打算在评论中留下这个,但是我的回答开始变得有点长了,所以这里是。。。在
正如@jornsharpe所说,
_T
是一个类类型参数,而不是一个函数类型参数。基本上,当您调用该方法时,mypy将具有:_KT
和{foo: MutableMapping[str, int] = ...
,然后调用foo.pop(...)
,mypy将理解在我们调用str
和{str
和{Mypy还将注意到,如果调用第二个重载,则有一个free(即unbound)类型的参数正在浮动。然后,它将尝试根据我们传入/周围上下文的任何值来推断正确的
_T
类型是什么。在例如,假设我做}分别绑定到}。然后Mypy注意到
foo.pop("x", "bar")
。这与第二个过载匹配。我们之前也说过,_KT
和{str
和{_T
是未绑定的,并尝试推断一个适当的类型。在在这里,我们知道我们传入的值的类型是“str”,参数类型是
Union[int, _T]
(在绑定类型中替换之后)。我们还知道,我们传入的值必须是参数的子类型,我们知道str
必须是Union[int, _T]
的子类型。在然后,Mypy使用上述所有信息/所有已知约束运行一个推理算法,并且能够在本例中推断}类型。
_T
必须是{(顺便说一句,mypy的推理算法在这里并不完美。如果表达式特别复杂/当前无法正确处理某些边缘情况,则有时可能无法推断正确的类型。)
如果您想更详细地描述mypy的类型推理算法是如何工作的,可以尝试通过mypy的代码库进行探索。具体来说,mypy调用this function,后者反过来调用code in here。好的警告,这有点难理解。在
我们知道}都是基于{a3}的不变量。在
_KT
,_VT
,和{这三个类型变量中的每一个都可以彼此完全独立。这与运行时行为相匹配:如果我有一个
Dict[str, str]
,那么执行my_dict.pop("x", 4)
可能会返回一些字符串或数字4,具体取决于my_dict
所包含的内容。在因此,完全抛开泛型,以下是mypy0.620中的重载规则(简化)。(早期版本的mypy使用了类似的但更灵活的即席算法)。在
然而,Mypy将禁止固有不安全过载定义。在以下情况下,两种过载变体被视为本质上不安全的:
在
pop
的特定情况下,第一个变量的参数确实与第二个变量兼容:无论出于什么原因,default
参数被标记为可选的。这意味着对foo.pop("x")
的调用实际上可以匹配这两个重载。在然而,第一个重载变量的返回类型是第二个重载变量的子类型:}的子类型,不管{}最终是什么。
_VT
是{这些规则并不是真的有意义的改变如果我们在混合中加入泛型。在
文档中有关于the nuances of function overloading的更多细节/示例。在
相关问题 更多 >
编程相关推荐