因此,不幸的是,Python/PEP 484中的数字系统目前有点混乱。
从技术上讲,我们有一个
"numeric tower"
这应该表示一组ABC,Python中所有“类似数字”的实体都应该遵循这些ABC。
此外,Python中的许多内置类型(例如
int
,
float
,
complex
和
timedelta
使问题复杂化的是
numbers module is largely dynamically typed
目前,您需要做的是:
-
安装
typing_extensions
模块(
python3 -m pip install typing_extensions
)
-
python3 -m pip install -U git+git://github.com/python/mypy.git
然后,我们可以为“支持添加或分割”类型定义协议,如下所示:
from datetime import timedelta
from typing import TypeVar, Iterable
from typing_extensions import Protocol
T = TypeVar('T')
S = TypeVar('S', covariant=True)
class SupportsAddAndDivide(Protocol[S]):
def __add__(self: T, other: T) -> T: ...
def __truediv__(self, other: int) -> S: ...
def avg(xs: Iterable[SupportsAddAndDivide[S]]) -> S:
it = iter(xs)
try:
s = next(it)
i = 1
except StopIteration:
raise ValueError("Cannot average empty sequence")
for x in it:
s += x
i += 1
return s / i
reveal_type(avg([1, 2, 3]))
reveal_type(avg([3.24, 4.22, 5.33]))
reveal_type(avg([3 + 2j, 3j]))
reveal_type(avg([timedelta(1), timedelta(2), timedelta(3)]))
test.py:27: error: Revealed type is 'builtins.float*'
test.py:28: error: Revealed type is 'builtins.float*'
test.py:29: error: Revealed type is 'builtins.complex*'
test.py:30: error: Revealed type is 'datetime.timedelta*'