Today I learnt about Python type hints šŸ

Up until today I knew type hints existed in Python and had read code which used them but hadnā€™t written any. I wanted to decide if this is a useful technique for me. Letā€™s say I have the following function:

def product(x, y):
    return x * y

I like the idea that I could automatically detect if someone calls it with parameters which arenā€™t numbers. I wrote a few different calls to test how the function behaves.

product(2, 4)
# Returns 8

product(2, -4)
# Returns -8

product(2.1, 4)
# Returns 8.4

product(2, True)
# Returns 2 a bit odd

product('a', 2)
# Returns aa which is unexpected

product('a', '2')
# Throws TypeError: can't multiply sequence by non-int of type 'str'

product('a', 'b')
# Throws TypeError: can't multiply sequence by non-int of type 'str'

Hereā€™s a type hint version of the same code:

def product(x: int, y: int) -> int:
    return x * y

I was hoping the Python interpreter would throw an exception if I call:

product('a', 2)

It doesnā€™t, so whilst type hints are useful for documenting what type of parameters should be used, and the return type, on their own type hints wonā€™t help catch errors.

Mypy

To get the behaviour I wanted I needed to install Mypy:

pip install MyPy

Then by running:

mypy my_python_file.py

I got the following output:

types_experiments.py:7: error: Argument 1 to "product" has incompatible type "float"; expected "int"
types_experiments.py:9: error: Argument 1 to "product" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)

Very good! However interestingly Mypy is ok with:

product(2, True)

So itā€™s happy with treating True as 1 which surprised me.

Python Number Type

My function calculates the product of two numbers, so Iā€™d expect the following to be a valid call:

product(2.1, 4)

However I specified the parameter types to be int so this isnā€™t valid and Mypy tells me off! Thereā€™s no ā€œnumber typeā€ in Python but PEP 484 states if we set the type to be float then an argument of type int is acceptable. So our function now looks like:

def product(x: float, y: float) -> float:
    return x * y

Conclusion

On the one hand I like Python type hints as they are adding extra detail to the code conveying how it should be used. It also feels similar to typing in Swift which Iā€™m a fan of. On the other hand the fact the Python interpreter ignores the type hints and youā€™re required to run checks separately with MyPy makes this feel a bit more of a faff, also I found Mypy a bit slow to run so maybe this would work best as a CI step.