Install mypy
with conda install -c anaconda-platform mypy
,
vim plugin 'w0rp/ale' (asynchronous lint engine, which embed mypy
into vim)
and 'python-mode/python-mode' (see dsnot Python IDE based on vim).
The following codes demonstrates how mypy
find typing incompatibility
before running the code:
$ cat << EOF > test.py
from typing import Iterable
def mean(items: Iterable) -> float:
return sum(items) / len(items)
EOF
$ mypy test.py
test.py:5: error: Argument 1 to "len" has incompatible type Iterable[Any]; expected "Sized"
Another example based on codes in chapter 10 of "Functional Python Programming", 2nd edition by Steve Lott:
Save the following codes into typecheck.py:
from typing import (Callable, Iterable, Any, TypeVar, Dict, Iterator,
List, Tuple, cast)
from functools import reduce
from operator import add
from collections import defaultdict
from itertools import groupby
T = TypeVar('T')
def map_reduce(mapf: Callable, reducef: Callable, source: Iterable) -> Any:
return reduce(reducef, map(mapf, source))
def mr2(mapf: Callable[[T], T], reducef: Callable[[T, T], T],
source: Iterable[T]) -> T:
return reduce(reducef, map(mapf, source))
data = [1, 2, 3, 5]
res = map_reduce(lambda x: x * 10, add, data)
print(res)
res = mr2(lambda x: x * 10, add, data)
print(res)
K = str # means "key"
D = Tuple[K, float]
inp: List[D] = [
('4', 6.1), ('1', 4.0), ('2', 8.3), ('2', 6.5), ('1', 4.6),
('2', 6.8), ('3', 9.3), ('2', 7.8), ('2', 9.2), ('4', 5.6),
('3', 10.5), ('1', 5.8), ('4', 3.8), ('3', 8.1), ('3', 8.0),
('1', 6.9), ('3', 6.9), ('4', 6.2), ('1', 5.4), ('4', 5.8)]
def partition(source: Iterable[D],
key: Callable[[D], K] = lambda x: cast(K, x)
) -> Iterable[Tuple[K, List[float]]]:
pd: Dict[K, List[float]] = defaultdict(list)
for item in source:
pd[key(item)].append(item[1])
for k in sorted(pd):
yield k, pd[k]
for key, group_iter in partition(inp, key=lambda x: x[0]):
print(key, list(group_iter))
def partition_s(source: Iterable[D],
key: Callable[[D], K] = lambda x: cast(K, x)
) -> Iterable[Tuple[K, Iterator[D]]]:
return groupby(sorted(source, key=key), key)
res = partition_s(inp, key=lambda x: x[0])
for key, groupIter in partition_s(inp, key=lambda x: x[0]):
print(key, list(groupIter))
If you change T = TypeVar('T')
to T = str
, there will be
an 'incompatible type ...error marked on function
mr2`.
The following codes shows the function of typing.cast
:
>>> from typing import cast
>>> cast(float, 3)
3
>>> type(cast(float, 3))
int
It returns the argument (here it's 3) itself.
And tell the type checker "I am a float variable".
While at runtime the Python interpreter will simply ignore
the cast
function and treat 3 as an integer.