Python Type Hinting and mypy
Python 3.5 introduced type hinting which I think is an awesome addition to the language. However, as the PEP 484 outlined there is no type checking happening at the runtime, and the primary rationale of the PEP seems to be adding a standard language for type annotations to enable static analysis. Still, the PEP says that type hinting opens Python potentially for runtime type checking while it emphasizes that Python will remain a dynamic language.
I think type checking at the runtime could work well; I have been programming recently in the PHP land, and I like PHP’s type hinting. However, you can turn on strict types on/off in PHP, which you (still?) don’t have in Python. Nevertheless, type hinting makes development easier even if you don’t have type checking at the runtime thanks to easier code completion in IDEs and making static analysis more powerful.
I think mypy type checker is a very useful tool. You can run it to check whether you have any type related bugs in your code. I think integrating it into your build pipeline is not a bad idea, and you might be able to catch some nasty bugs with it. Below a very short introduction to mypy:
Consider the following:
class A: def __init__(self, i: int): self.i = i def should_return_int(self, string: str)->int: return str(self.i) + string
If you have ran the code on mypy, you would get the following:
typehints.py: note: In member "__init__" of class "A": typehints.py:2: error: The return type of "__init__" must be None typehints.py: note: In member "should_return_int" of class "A": typehints.py:6: error: Incompatible return value type (got "str", expected "int")
Type hinting also makes it easier to deal with abstract classes (and inheritance in general):
import abc class AbstractClass(abc.ABC): @abc.abstractmethod def some_getter_method(self)->str: pass @abc.abstractmethod def some_setter_method(self, name: str): pass class ConcreteClass(AbstractClass): def some_getter_method(self) -> str: return self.name def some_setter_method(self, name: str): self.name = name def expects_abstract_class(argument: AbstractClass)->str: return argument.some_getter_method() concrete_instance = ConcreteClass() concrete_instance.some_setter_method("John Doe") expects_abstract_class(concrete_instance) expects_abstract_class(object())
Running the code on mypy would yield the following warning:
Argument 1 to "expects_abstract_class" has incompatible type "object"; expected "AbstractClass"















