This is a super important concept if you are working on a serious project that you expect to work on for years. As you might know Python is a dynamically typed language, So, the interpreter doesn't check types at the compile-time rather it does this task in runtime.
Let's review this in action
count = 5
print(type(count))
<class 'int'> #output
count = '5'
print(type(count))
<class 'str'> #output
Initially, when we assigned the number 5 to the variable count, It is inferred as an Integer object. However, in Python, we can re-assign some other type value in the count variable. This is possible because Python recognizes data types during runtime.
Why this behavior?
Python is concentrated on the convenience of the developers. So, it internally takes care of the tasks like type checks.
Why Type Hints?
The goal is to increase developer productivity by:
- Helping IDEs recognize the types. This in turn leads to better suggestions by IDEs.
- If you sprinkle your code with type annotations, mypy, and similar static type checkers can type-check your code and find common bugs 🐛🪲.
For these reasons, We see support for type-hints from Python version 3.4+. The basic idea is to annotate the variables and functions to give indications of what they are expecting. Let's see an example:
def total_price(price_1,price_2):
return f"Your total bill is USD {price_1+price_2}"
print(total_price(30,40))
As you might have already understood, This function will print: 'Your total bill is USD 70'
. Nice. looks like it works correctly, but what will happen if we pass a string to the function?
def total_price(price_1,price_2):
return f"Your total bill is USD {price_1+price_2}"
total_price('30','40')
For strings, + operator is overloaded and it works like a concatenation! This will result in 'Your total bill is USD 3040'
! To identify such bugs in the development phase only, We can make use of static type checkers like mypi, pylance, pyre, etc. They require the identifiers to be annotated beforehand, So, that they can identify the types and give feedback on our code. Now, let's see how type-hinting actually benefits us.
1. Better IDE Support
It becomes easier for IDEs to understand the types of identifiers. Thus the autocomplete works better. We get relevant suggestions from the IDEs.
2. Better Developer Experience.
When we hover over the function or class, IDEs present us with the function definition along with arguments and their types. This is especially useful for the new joiners. They need not debug our complete code and understand what to pass. This saves time in the long run. Actually no, We mostly forget our implementation in 1-2 months. Thus, it is essential for ourselves too🤭.
3. Fewer Bugs 🐛🪲.
As we saw previously, It was such an easy task to break the total_price function. All, it needed was to pass string value.
def total_price(price_1,price_2):
return f"Your total bill is USD {price_1+price_2}"
total_price('30','40')
This can be resolved using type annotations, Let us refractor it by adding type hints:
# filename typehints.py
def total_price(price_1:int,price_2:int):
return f"Your total bill is USD {price_1+price_2}"
price = total_price('30','40')
To proceed with static type checking, follow the below steps:
1. Install mypy in your virtualenv, with pip install mypy==0.941
2. Go to your python file path in the terminal and type: mypy filename.py
You should see the below output:
(env) C:\Users\soura\v2\pre-req\basics> mypy .\1_type_hints.py
1_type_hints.py:4: error: Argument 1 to "total_price" has incompatible type "str"; expected "int"
1_type_hints.py:4: error: Argument 2 to "total_price" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)
We can also specify the return type of the function, all we need to do is change the function definition to:
def total_price(price_1:int,price_2:int) -> str: That's it for this one, In the next article we will review some of the advanced features of the typing module.
Gotcha: If you have watched Dr. Strange, You might remember that warnings are written at the last😁.
⚠️Type hints do not imply that Python is now a statically typed language. Python Interpreter will behave in the very same way, Our crush behaves with us. Exactly, Type hints will be ignored!😁
The type annotations are not enforced by the Interpreter. For instance, even if I specify the function return type as Integer and return a string, the Python interpreter won't complain.