如果我想要注释只需要__len__的容器,我会将其注释为类型:(大小) – > INT.如果我想注释一个只需要__iter__的容器,我会将其注释为类型:( Iterable [int]) – > INT.但是,如何在我需要的容器中完美地注释容器?
编辑:
我根据piotr-Ćwiek的建议尝试了这个:
from __future__ import print_function from typing import Sized,Iterable class SizedIterable(Sized,Iterable[int]): pass def product2(numbers): # type: (SizedIterable) -> int if len(numbers)%2 == 1: return 1 else: p = 1 for n in numbers: P*= n return p print(product2([1,2,3,4])) print(product2({1,4}))
但是这个错误失败了:
prod2.py:17: error: Argument 1 to "product2" has incompatible type List[int]; expected "SizedIterable" prod2.py:18: error: Argument 1 to "product2" has incompatible type Set[int]; expected "SizedIterable"
解决方法
SizedIterable不起作用的原因是通过从Sized和Iterable派生它,你只是告诉mypy它是这两种类型的子类型; mypy并不认为任何类型为Sized和Iterable的子类型也是SizedIterable的子类型.
Mypy是完全合乎逻辑的;毕竟,您不希望此代码键入check:
class A(Sized,Iterable[int]): def g(self) -> None: ... def f(x: A) -> None: a.g() # passes type check because [1,2] is Sized and Iterable # but fails in run-time f([1,2])
如果mypy以不同的方式处理你的类定义只是因为它的类体是空的,那就太麻烦了.
为了让mypy理解你的意图,mypy需要为其类型系统添加一个新功能.
目前正在考虑这种功能的两个选项:
> intersections(由@PiotrĆwiek指出);你要求的是Iterable和Sized的交集
> structural typing;这比一般的交叉点简单得多,但对于你的用例来说已经足够了,因为你需要的只是number参数有__len__和__iter__方法
模仿输入类定义或使用__instancecheck__将无法工作,因为(正如有人最近向我解释过的)在任何情况下mypy都不会运行您编写的代码(即,它永远不会导入您的模块,永远不会调用您的函数等) .这是因为mypy是一个静态分析工具,它不会假设运行代码的环境在执行期间甚至可用(例如,python版本,库等).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。