Contents

Type hinting in Python

For my master’s thesis I’ve been needing to do a lot of Python development. It started out small and neat, but as time passed and features got implemented, my data structures got a bit messy.

So from originally just functions, I slowly extracted classes to properly model my data. And as I got more and more classes I started to abstract them using inheritances.

But Python’s messy class system has always been a little thorn in my side. It’s a nice language, I like reading and writing in it. But that whole dynamic typing can be a bit of a pain. Type hinting makes writing larger applications in Python way more solid.

Enter type hints

Type hints are a new-ish addition to Python. Originall proposed in PEP 484 and PEP 526, it is now an established part of many current Python projects.

To annotate a variable with a type, simply append its type like this:

1
2
3
greeting: str = "Hello user number "
counter: int = 25
print(greeting + str(counter))

Of course this is a trivial example. You know that the types are a string and an integer respectively since you define it in the same line. But how about this?

1
2
3

def dijkstra_path(G, source, target, weight='weight'):
    pass

Now, without reading the code, docstrings or external documentation of the library, you’re pretty screwed and have to guess. What is G? The graph? What are source and target? I can see that weight is a string, but does the function return something?

Now compare it with this:

1
2
3

def dijkstra_path(G: Graph, source: Node, target: Node, weight='weight') -> List[Node]:
    pass

This variant is a lot more verbose and gives you a ton of information, without even dropping a comment. We can now tell that the function requires a Graph and two Nodes and then returns you the path between the nodes as a List. It also gives you information about some of the data structures used. You may not have seen a Node in this context before and now know that a construct like this exists. Neat!

But it doesn’t DO anything!

Yes, you are right on that. The Python interpreter does not care about your type hints. That’s why they are just hints. Sadly, they don’t give you any performance benefits either.

In fact, the following snippet will work without any problems.

1
2
3
# Valid Python code, even if the type hints are wrong.
counter: int = "25"
print("The current counter is: " + str(counter))

Obviously, the type of the counter is incorrect, but since the interpreter completely ignore type hints, this expression is completely valid and will execute without even a warning.

…But it’s still worth it

This is an issue, but it does not mean type hints are useless. For once, they make sure your code is self-documenting. A function header with type hints is easier to read and understand than a function that does not add types. Just compare it yourself, which one would you rather read:

/media/type_hints_no_types.png

or

/media/type_hints_with_types.png

As developers, we read more code in a day then we actually write. I think striving to write good and readable code is very important. Of course you can use docstrings or just more comments to make your code easier to understand, but adding type hints is a small change that can easily improve your code quality.

Think before you act

Apart from just documenting your code, I believe it also makes you think more about your code. It’s very easy to just define a function with some parameters and plan to take care of the implementation details later. But specifying the function header with types in mind, shifts your focus from planning ahead with “some input thingy” to something that is expected to be “this type”.

And that’s exactly how these hints need to be understood as a user. Since the interpreter does not care, type hints are a contract between developers. If I define a function with two strings as parameters, then I expect another developer to provide me with two strings. In return, I will make sure the function safely works. Of course you can instead give me two integers. Hell, it might still work then or crash horribly. But I can at least communicate to you what I intended to receive.

Type hints are a good IDEa

To be honest, my biggest selling point on type hints was good IDE support. Working on a medium sized project, I found myself jumping around between definitions a lot. Oftentimes I re-read a function I called just to figure out what kind of return type I was expecting. Sometimes I would have to dig even deeper to check the underlying type of the object to make sure I access the correct fields and methods.

/media/type_hints_ide.png Delicious IDE support

Type hints absolutely made me more productive in the way that it makes me understand code better. No more searching around in library internals for types that I need.