Mypy:如何正确猜测类型?
考虑以下示例
from typing import Callable, Iterable, TypeVar, Any, overload, Tuple, TYPE_CHECKING
from itertools import islice
T = TypeVar("T")
@overload
def mytake(n:int, iterable:Iterable[T]) -> Tuple[T,...]:...
@overload
def mytake(n:int, iterable:Iterable[T], container:Callable[[Iterable[T]],Any]) -> Any:...
def mytake(n:int, iterable:Iterable[T], container:Callable[[Iterable[T]],Any]=tuple) -> Any:
return container(islice(iterable,n))
if TYPE_CHECKING:
pass
else:
reveal_type = print
#a:tuple[int,...]
a = mytake(10,range(100))
reveal_type(a)
#b:list[int]
b = mytake(10,range(100), list)
reveal_type(b)#desired to be list[int]
#c:int
c = mytake(10,range(100),sum)
reveal_type(c)#desired to be int
help(mytake)
,
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
45
Help on function mytake in module __main__:
mytake(n: int, iterable: Iterable[~T], container: Callable[[Iterable[~T]], Any] = <class 'tuple'>) -> Any
即基本上是愿望,但是我希望Mypy
C:\Users\copperfield\Desktop\mypy_tests>mypy test6.py
test6.py:21: note: Revealed type is "builtins.tuple[builtins.int, ...]"
test6.py:25: note: Revealed type is "Any"
test6.py:29: note: Revealed type is "Any"
Success: no issues found in 1 source file
C:\Users\copperfield\Desktop\mypy_tests>
在暗示变量本身的类型旁边是一样的,是否有一种方法可以使它如此正确地检测到这里的类型?
consider the following example
from typing import Callable, Iterable, TypeVar, Any, overload, Tuple, TYPE_CHECKING
from itertools import islice
T = TypeVar("T")
@overload
def mytake(n:int, iterable:Iterable[T]) -> Tuple[T,...]:...
@overload
def mytake(n:int, iterable:Iterable[T], container:Callable[[Iterable[T]],Any]) -> Any:...
def mytake(n:int, iterable:Iterable[T], container:Callable[[Iterable[T]],Any]=tuple) -> Any:
return container(islice(iterable,n))
if TYPE_CHECKING:
pass
else:
reveal_type = print
#a:tuple[int,...]
a = mytake(10,range(100))
reveal_type(a)
#b:list[int]
b = mytake(10,range(100), list)
reveal_type(b)#desired to be list[int]
#c:int
c = mytake(10,range(100),sum)
reveal_type(c)#desired to be int
help(mytake)
that ouput
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
45
Help on function mytake in module __main__:
mytake(n: int, iterable: Iterable[~T], container: Callable[[Iterable[~T]], Any] = <class 'tuple'>) -> Any
Basically just as desire, but I would like that mypy was the same
C:\Users\copperfield\Desktop\mypy_tests>mypy test6.py
test6.py:21: note: Revealed type is "builtins.tuple[builtins.int, ...]"
test6.py:25: note: Revealed type is "Any"
test6.py:29: note: Revealed type is "Any"
Success: no issues found in 1 source file
C:\Users\copperfield\Desktop\mypy_tests>
Beside type hinting the variables themselves, is there a way to make it so mypy correctly detect the types here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,有条件。超负荷分辨率正在推动Mypy已经紧张的功能的边缘,因此我们可以接近。
您想要的是额外的通用,用于可可的返回类型。
请注意,我们必须在案例1中进行施放,因为Mypy不考虑在功能的内部检查时可用的过载。因此,正如人类读者一样
可选[Callable [[iToble [t]],s]]
。这是一个安全的演员,只有一个mypy就没有得到。这是我们想要的签名,但是可以使用它很尴尬。
第一个仍然按预期工作。
第二个不起作用。实际上,我们会遇到一个错误。 mypy具有一些问题 将类型解释为
callable
实例通用上下文,因此我们可以使用lambda解决此问题。不理想,但可行。
第三个不是那么幸运。
老实说,我什至不确定这里会发生什么。 mypy报告
c
的类型是union [_t
-1,inceartins.int]。因此,
int的结合和无法解决的metavar。迷人的。我怀疑这与以下事实有关: Noreferrer“>几个通用过载,可能只是使Mypy感到困惑。同样,我们可以用明确的lambda解决它。
因此,答案是肯定的,如果您愿意通过慷慨地插入
lambda
来帮助类型的检查器。但是这种事情将Mypy推到了极限。我不确定其他类型的检查器在这种情况下是否会做得更好,因为我对Mypy最熟悉。如果有人与另一个Python类型检查器尝试了此操作,请随时发布您的结果。Yes, with provisos. Overload resolution is pushing on the edge of mypy's already strained capabilities, so we can get close-ish.
What you want is an additional generic, for the return type of the callable.
Note that we have to cast in Case 1, as mypy doesn't consider the overloads that are available when type-checking the inside of the function. So we, as human readers, can conclude that, inside that
if
statement, we're in Overload 1, but mypy is still considering thatcontainer
could be anyOptional[Callable[[Iterable[T]], S]]
. It's a safe cast, just one mypy doesn't quite get.This is the signature we want, but it's awkward to work with.
The first one still works as intended.
The second one won't work. We actually get an error. Mypy has some issues with interpreting types as
Callable
instances in generic contexts, so we can get around this using a lambda.Not ideal, but workable.
The third one is not so lucky.
To be quite honest, I'm not even sure what happens here. Mypy reports that the type of
c
isUnion[_T
-1, builtins.int]. So a union of
intand an unsolved metavariable. Lovely. I suspect this has to do with the fact that
sum` has several generic overloads and is probably just confusing mypy. Again, we can get around it with an explicit lambda.So the answer is yes, if you're willing to help the type checker out by generously inserting
lambda
everywhere. But this sort of thing pushes mypy to its limit. I'm not sure if other type checkers would do better generic inference in this case, as I'm most familiar with mypy. If someone has tried this with another Python type checker, feel free to post your results as well.