Type Hinting
Type Hints were added to python 3.5 as a way of adding support for linters and 3rd party tools to check code for possible errors. These have no effect of the running of the code and are not mandatory, however they are good software engineering practice and we encourage their use throughout your code.
Example file
#!/usr/bin/env python
import cmath
def quadratic_roots(a, b, c):
"""calculate the quadratic roots of a, b, and c are coefficient and real numbers and also a ≠ 0.
If a is equal to 0 that equation is not valid quadratic equation.
Parameters
----------
a : number
b : number
c : number
Returns
-------
first : number
second : number
Raises
------
ValueError if a == 0
"""
if a == 0:
raise ValueError
discriminant = (b**2) - (4 * a * c)
first = (-b - cmath.sqrt(discriminant)) / (2 * a)
second = (-b + cmath.sqrt(discriminant)) / (2 * a)
return first, second
# This will return a complex result
a, b = quadratic_roots(2, 3, 4)
print(f"{a} {b}")
# This will return a complex but with zero j
a, b = quadratic_roots(1, 4, 2)
print(f"{a} {b}")
# This will throw an exception
try:
a, b = quadratic_roots(0, 4, 2)
print(f"{a} {b}")
except ValueError:
print("a was zero!")
a, b = quadratic_roots("1", "4", "2")
print(f"{a} {b}")
if we run this program we get an error
./function.py
(-0.75-1.1989578808281798j) (-0.75+1.1989578808281798j)
(-3.414213562373095+0j) (-0.5857864376269049+0j)
a was zero!
Traceback (most recent call last):
File "/Volumes/teaching/Code/ASEAIM/Lab2/./function.py", line 49, in <module>
a, b = quadratic_roots("1", "4", "2")
File "/Volumes/teaching/Code/ASEAIM/Lab2/./function.py", line 27, in quadratic_roots
discriminant = (b**2) - (4 * a * c)
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
We can also run mypy on it which reports
mypy function.py
Success: no issues found in 1 source file
Adding Type Hints
from typing import Any, Tuple
# Note float type hint will also support int as a number
def quadratic_roots(
a: float, b: float, c: float
) -> Tuple[Any[float, complex], Any[float, complex]]:
The function has now added type hints for the parameters as well as the return type. Running the new program still causes the same errors with the string parameters however running mypy on the file gives the following.
mypy functionTypeHint.py
functionTypeHint.py:53: error: Argument 1 to "quadratic_roots" has incompatible type "str"; expected "float"
functionTypeHint.py:53: error: Argument 2 to "quadratic_roots" has incompatible type "str"; expected "float"
functionTypeHint.py:53: error: Argument 3 to "quadratic_roots" has incompatible type "str"; expected "float"
Found 3 errors in 1 file (checked 1 source file)
These errors will usually show in vscode if we setup the python tools to use mypy (or pylance).
Stub Files
It is also possible to add type hints to a separate file called a
“stub file” typically this will have the extension .pyi
from typing import Any, Tuple
# Note float type hint will also support int as a number
def quadratic_roots(
a: float, b: float, c: float
) -> Tuple[Any[float, complex], Any[float, complex]]: ...
Stub files only work with imported modules so we can test using a simple file.
#!/usr/bin/env python
from functionStubFile import quadratic_roots
# This will return a complex result
a, b = quadratic_roots(2, 3, 4)
print(f"{a} {b}")
# This will return a complex but with zero j
a, b = quadratic_roots(1, 4, 2)
print(f"{a} {b}")
# This will throw an exception
try:
a, b = quadratic_roots(0, 4.2, 2)
print(f"{a} {b}")
except ValueError:
print("a was zero!")
a, b = quadratic_roots("1", "4", "2")
print(f"{a} {b}")
Running the following now spots the errors
mypy testStubFile.py
testStubFile.py:20: error: Argument 1 to "quadratic_roots" has incompatible type "str"; expected "float"
testStubFile.py:20: error: Argument 2 to "quadratic_roots" has incompatible type "str"; expected "float"
testStubFile.py:20: error: Argument 3 to "quadratic_roots" has incompatible type "str"; expected "float"
Found 3 errors in 1 file (checked 1 source file)