If this helped you, please share!

Python type hints: alias those types!

Published February 21, 2018 in programming - 0 Comments

All python code is Python 3.5+.

PEP484 goes beyond built-in type annotations. Another feature of the Python type hinting libary is the ability to create type aliases. I’ve used type aliasing frequently in C++ (typedef, using) to improve code readability and for its other benefits. I’m happy to see that it’s available in Python too.

Here is an example of a Point class that should have int or float coordinates. The type hint is set up using a type alias created using a type hint variable. The class itself needs to inherit from the typing module Generic class to use the alias.

Using the expected coordinate type in the Point class is not enforced at runtime, but can be checked in a linting step by type hint aware static type checker tools like mypy.

So what’s actually happening in the code?

The type hint T is declared as a type alias with constraints. Point coordinates will be constrained by a static type checker to either int or float.

T = TypeVar('T', int, float)

The point class is made generic (with constraints) by having member variables of type T be either int or float types. The constructor also uses type comments, which are processed by type checkers, to clarify member variable types. Type comments are a nice and easy way to improve code readability in longer, more complex constructors.

class Point(Generic[T]):
    def __init__(self, x: T, y: T) -> None:
        self.px = x # type: T
        self.py = y # type: T

Type hints can be used in properties, although there shouldn’t be any ambiguity about return types here:

    def x(self) -> T:
        return self.px

    def y(self) -> T:
        return self.py

To use the containing class as a type hint, we need to use forward references. A type checker will resolve the ‘Point’ string in the argument list to the correct type:

    def distance_point_coordinates(self, px: T, py: T) -> float:
        x_diff = self.px - px
        y_diff = self.py - py
        return sqrt( x_diff*x_diff + y_diff*y_diff )

    def distance(self, point: 'Point') -> float:
        x_diff = self.px - point.x
        y_diff = self.py - point.y
        return sqrt( x_diff*x_diff + y_diff*y_diff )

A type comment makes the intended use of the polyline list clearer:

polyline = [] # type: List[Point]

This still doesn’t stop me from appending a variable with the wrong type as shown in the third cell.

Type hint error

A static type checker like mypy will catch and report this however. Linting is a good practice for producing quality code. Adding type hint checking is a reasonable addition to this practice.

Tags: python

No comments yet

Leave a Reply: