Python handles it’s type definitions in a very different way from other languages like C++ and Java. Python uses dynamic typing, which doesn’t require variables to be declared with a type. This can become very confusing very quickly, in larger applications. To resolve this issue, or atleast minimize it, Python introduces the concept of Type hinting.
Type hinting, also known as type annotation, is a way for us, the programmer to hint at the type of the object we are using. The full story is a bit more complicated, so let’s take a look at the entire process step-by-step.
Pre-requisites for Type Checking
An important thing to note, is that Type Hinting by itself doesn’t perform Type Checking. There is a slight difference between the two terms.
Type Hinting is a feature introduced in Python 3.5, which we, the programmers can use to tell type checkers what the type of the object we are using, is.
On the other hand, Type Checking is the actual act of checking whether the type of object, and the type of the value being used with it, are of the same type. Type Checkers are responsible for raising errors when an invalid case has been detected. (More specifically, we need a static type checker, not a dynamic one)
So in a way, we can say that Type Hinting + Type Checker = Type Checking. Now we have Type Hinting, but what about the Type Checker? Well we can use a popular python library for that, called mypy, used for Static Type Checking.
Simply download mypy using pip, and then you can continue along with the tutorial.
pip install mypy
Introduction to Type Hinting
So let’s take a look at a small example first. Let’s say we want to create a function which adds together two integers. For this we would create the following function.
def add(one, two):
return (one + two)
And if wanted to call it, then we would do:
add(5, 6)
But here we have a slight flaw. Though some may consider it a feature, it may also be considered a flaw. We created this function to add together two integers, but the following function call with two strings is also valid!
add("Hello", "World")
Why is this so? This is because of dynamic typing of course, and it is something we are going to rectify with Type hinting and the static type checker mypy. There are a few more benefits of Type hinting, that we will discuss towards the end of this article.
Just to clarify, our goal is to ensure only integers can be passed to this function, and that only integers can be returned.
Implementing Type Hinting in Python
Let’s take a quick detour and discuss how to implement type hinting on a single variable first. Normally when you assign a variable a value, you use the following pattern:
var = 5
Now the problem with this is that the variable “var
” is not binded to any type, which is what dynamic typing is all about. So the following move would be legal in Python:
var = 5
var = "Hello"
Now if you tried this in C++ or Java, it wouldn’t work. So how do we bring about the same thing in Python?
The first step is to use type hinting. To do so, the following format must be adopted, where we have the variable name, followed immediately by a colon, followed by the type of the variable, then the equal sign, followed by the value you wish to assign.
var: int = 5
Alternatively, you can just declare the variable, and assign a variable later.
var: int
var = 5
This now tells the Type Checker that var
only accepts int
values.
Type Hinting on a Function
Now let’s take a look at how to use type hinting with a function.
The parameters will be declared with the method we just discussed in the previous section. We do however need to mentioned the return type. This is done by including an arrow using ‘-‘ and ‘>’ characters, following by the return type, after the parameter list of the function, but before the colon.
The below example is the add()
function we were discussing earlier, but with type hinting applied.
def add(one: int, two: int) -> int:
return (one + two)
Now if we try the following function call…..
add("Hello", "World")
…It’s still going to work! Why is that? Well this is because we are still running it normally.
Unless you are using an IDE with static type checking built in, this will not raise an error. This is why we need to use mypy
, as it is a static type checker. Any other static type checker will also do, if you wish to use some other alternative.
So let’s run this using mypy
. You don’t need to import it, rather you need to run the following command in the terminal (You can either use the CMD, or the built in terminal in IDE’s like PyCharm and Visual Studio Code). Remember to include the full filepath to the file if you aren’t running this command in the same directory as the file.
mypy filename.py
or if this doesn’t work,
python -m mypy filename.py
This runs the python code in the file using mypy
, rather than the standard Python interpreter.
If we now run the following code using this command….
def add(one: int, two: int) -> int:
return (one + two)
print(add("Hello", "World"))
We will get the following output.
PS D:\VSCode_Programs\Python> python -m mypy typehinting.py
typehinting.py:9: error: Argument 1 to "add" has incompatible type "str"; expected "int"
typehinting.py:9: error: Argument 2 to "add" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)
One error for each invalid argument.
With this our objective has been complete, and type hinting for both variables and functions has been implemented.
Python Typing Library
Along with Type hinting, python also introduced the typing library, which brings in some additional features for type checking and new ways to define the type of objects.
Previously, we could only declare the type of variables and functions. But now, with the Typing library, we can even define the type of Lists, Dictionaries, Tuples and other Python objects.
Let’s take a look at some short examples.
from typing import List, Tuple, Dict
# List of Strings
a: List[str]
# Dict with strings as keys, and integers as values
b: Dict[str, int]
# Tuple of ints
c: Tuple[int]
Attempting something like this…
a: List[str] = ["1", "2"]
a.append(3)
gives us the following error, as it only accepts string values.
PS D:\VSCode_Programs\Python> python -m mypy typehinting.py
typehinting.py:8: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
Found 1 error in 1 file (checked 1 source file)
We can even combine together several types, using the Union keyword.
from typing import List, Dict, Tuple, Union
mylist: List[Union[int, str]] = ["a", 1, "b", 2]
The above command is perfectly valid, as both int
and str
are allowed in mylist
.
To learn more about the Typing library, and the various keywords it introduces, refer to our Tutorial on the Python Typing Library.
This marks the end of the Python Type Hinting Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.