0

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)
10
  • For starters, Iterable won't work, because not all iterables support computing their length. The closest available type is collections.abc.Collection, which subclasses Sized and Iterable, but also requires __contains__. If you need to stick with Iterable, you'll need to use something less efficient to compute the length while computing the sum. Commented Dec 17, 2024 at 14:05
  • Type-wise, the default starting value of 0 used by sum isn't appropriate for any possible type bound to T. You've gotten lucky in your testing that 0 is sufficient at runtime. You may need to bound or constrain T to number-like types, but I don't know if there's an easy way to do that which incorporates NumPy arrays, matrices, etc. Commented Dec 17, 2024 at 14:06
  • You might want to see how sum is typed in the first place, starting here. Commented Dec 17, 2024 at 14:29
  • (Looking at sum, there is an overload that ignores the starting value, so that may not play into the weird inference of bool as I speculated it might.) Commented Dec 17, 2024 at 14:44
  • Indeed. Iterable is not good type hint, for my needs Sequence would be more than enough. So I tried this, and changed sum function into manual loop, errors now are different Commented Dec 17, 2024 at 15:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.