Type Hints Annotations in Python

Diane Khambu
Geek Culture
Published in
3 min readApr 2, 2022
Photo by Amit Rai on Unsplash

Came across functions in Python that had inline annotation of arguments passed to the function and annotated return type as well. It looked so similar to Dafny and Lustre language that I’d learned in Formal Methods class in graduate school. Was a bit surprised that their exist such a feature in Python, also thought that it should be used more often! Makes code so much readable and comprehensible, also a time saver in large codebase if the code does not have docstring. This starter was written at least a year ago, so taking out of my priority-queue. 🦾

Hence, we are diving into type hints annotation in python by looking at some common and useful types with examples. Let’s look at some common annotations:

typing module support type hints. The most common support consists of Any , Union, Callable , TypeVar .

Here is a simple method being annotated.

Method annotation

As we see, we annotate arguments after colon and return type is indicated by a forward arrow.

Now let’s check type aliases:

type alias example

Here we used, Matrix as an alias for more complex type signature, as in the example list[list[int]] .

Now let’s look at NewType type.

On running the file, the output is:

Natural Flowers: Calla Lily, Hibiscus
Hybrid Flowers: Stargazer, Hardy Hibiscus

We used NewType to create our custom type Flower by subclassing from the original type str . We are able to do string operations on the new types. We are able to further subclass the Flower type and create type HybridFlower .

Let’s see a method with these new types in actions:

On running the file, we get:

Calla lily

However, we cannot subclass the NewType in class. For example:

class FlowerInventory(Flower):
pass

gives TypeError .

Now, let’s look at Callable type.

Here, Callable is get_next_10_items method. We see that the Callable has a syntax of Callable[[arg1_type, arg2_type], return_type] . We can also substitute call signature with literal ellipsis like Callable[[...], return_type] . Even return type can be ellipsis.

Now let’s look at Generics . Since objects kept in containers cannot be statically inferred in generic way, collections.abc module has been extended to support types of elements in containers.

See the function signature in line number 7, we know that bouquets is a collection of Flower object types and address is a map of Flower object types and strings. Generics can also be parameterized by using available factory typing called TypeVar .

See, we are able to have a function with collection of objects of any types and get the last item.

Now let’s look at Any . A static type checker will treat every type as being compatible with Any and Any as being compatible with every type.

See, we are able to change variable a whose original type is Any to string and list. We can even assign int type with a ‘s value! A function’s return type is implicitly Any if return type is not mentioned.

Now let’s go to Union . Union[X, Y] is equivalent to X | Y which means X or Y .

See the return type is Union of Rock , Paper , or Scissor type.

Now, let’s look at Optional type. Optional[X] means X | None . Beware, this is not same arguments with default values.

See, while calling the method own_pet we can pass either Cat instance or None object! We are also taking care of return type by using Optional type!

That’s all for the article! Congratulations on the completion.

In summary, Python supports type hinting.

I hope the article gives you more insight into annotation in Python and maybe use them in your code base more often?!

See you soon in my next article. 🦔

Inspiration:

You can support me on Patreon!

--

--