I want to achieve something like this:
from collections import deque
from typing import Iterable
import numpy as np
def mean[T](a: Iterable[T]) -> T:
s = sum(a)
return s * (1.0/len(a))
c = mean([1.0, 1.5])
print(c)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = mean([a, b])
print(c)
print(mean((1,2,3)) )
d = deque([a,b])
print(mean(d))
but I want that code not only correctly work - which is achieved now, but also to be accepted by mypy. As for now I can't overcome errors like this:
mypy mypy_explore.py
mypy_explore.py:8: error: Argument 1 to "sum" has incompatible type "Iterable[T]"; expected "Iterable[bool]" [arg-type]
mypy_explore.py:9: error: Unsupported operand types for / ("float" and "int") [operator]
mypy_explore.py:9: error: Argument 1 to "len" has incompatible type "Iterable[T]"; expected "Sized" [arg-type]
mypy_explore.py:17: error: Incompatible types in assignment (expression has type "ndarray[Any, dtype[Any]]", variable has type "float") [assignment]
Found 4 errors in 1 file (checked 1 source file)
I have tested many methods, also using Protocol, but none of them successfully, I feel that this should be easy to achieve, just a sequence of any type supporting sum and multiplication by number should be accepted, but it is not...
I tried also this:
from collections import deque
from typing import Sequence
import numpy as np
def mean[T](a: Sequence[T]) -> T:
la = list(a)
s = a[0]
for i in la[1:]:
s = s + i
return s * (1.0/len(a))
c = mean([1.0, 1.5])
print(c)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = mean([a, b])
print(c)
print(mean((1,2,3)) )
d = deque([a,b])
print(mean(d))
and errors where like this:
mypy_explore.py : 4 errors
Unsupported left operand type for + ("T") [operator] (11:12)
Unsupported operand types for * ("T" and "float") [operator] (12:11)
Incompatible return value type (got "float", expected "T") [return-value] (12:11)
Incompatible types in assignment (expression has type "ndarray[Any, dtype[Any]]", variable has type "float") [assignment] (20:4)
Iterablewon't work, because not all iterables support computing their length. The closest available type iscollections.abc.Collection, which subclassesSizedandIterable, but also requires__contains__. If you need to stick withIterable, you'll need to use something less efficient to compute the length while computing the sum.0used bysumisn't appropriate for any possible type bound toT. You've gotten lucky in your testing that 0 is sufficient at runtime. You may need to bound or constrainTto number-like types, but I don't know if there's an easy way to do that which incorporates NumPy arrays, matrices, etc.sumis typed in the first place, starting here.sum, there is an overload that ignores the starting value, so that may not play into the weird inference ofboolas I speculated it might.)