我正在尝试为以下函数(Python 3.6,mypy 0.521)提出完美的函数签名:
def avg(xs):
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
这段代码的好处在于,它可以与 , , 的可迭代对象一起工作,并产生正确的结果,int
但也可以为. 尝试添加签名时会出现问题。我尝试了以下方法:float
complex
datetime.timedelta
def avg(xs: t.Iterable[t.Any]) -> t.Any: ...
但是现在,调用者需要转换结果。
def avg(xs: t.Iterable[T]) -> T: ...
这失败了,因为T
不支持加法或除法。
N = TypeVar("N", int, float, complex, datetime.timedelta)
def avg(xs: t.Iterable[N]) -> N: ...
失败是因为int / int
是float
; using//
几乎对其他所有内容都给出了错误的结果。也很糟糕,因为代码应该适用于其他类型,只要支持加法和除法。
N = TypeVar("N", float, complex, datetime.timedelta)
def avg(xs: t.Iterable[N]) -> N: ...
这几乎是完美的,但同样,如果有人后来决定向它扔四元数,mypy 会抱怨。
...然后我也尝试了一些东西,abc
但这typing.overload
让我无处可去。
最优雅的解决方案是mypy --strict
什么?