# Aims

We will investigate some modern python features and concepts by developing some small programs.

# 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

"""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


from typing import Any, Tuple

# Note float type hint will also support int as a number
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
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

# 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)