python-course.eu

2. Type Annotations For Functions

By Bernd Klein. Last modified: 13 Jul 2023.

Type annotations supply also a specific syntax to indicate the expected types of function parameters and the return type of functions.

A funny function

A simple Pyhon example of a function with type hints:

%%writefile example.py

def greeting(name: str) -> str:
    return 'Hello ' + name

# We call the function with a string, which is okay:
greeting("World!")  

# an integer is an illegal argument, it should a str:
greeting(3)    

# A bytes string is not the right kind of a string:
greeting(b'Alice')  

def bad_greeting(name: str) -> str:
    return 'Hello ' * name  # Unsupported operand types for * ("str" and "str")

OUTPUT:

Overwriting example.py
!mypy example.py

OUTPUT:

example.py:9: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"
example.py:12: error: Argument 1 to "greeting" has incompatible type "bytes"; expected "str"
example.py:15: error: Unsupported operand types for * ("str" and "str")
Found 3 errors in 1 file (checked 1 source file)

The following Python function of an annotated function shows a slightly more extended function definition:

def greeting(name: str, phrase: str='hello') -> str:
    return phrase + ' ' + name

We can see the annotations of a function by looking at the __annotations__ attribute:

greeting.__annotations__

OUTPUT:

{'name': str, 'phrase': str, 'return': str}

The __defaults__ attribute shows us the default values of the function:

greeting.__defaults__

OUTPUT:

('hello',)

These function annotations are available at runtime through the __annotations__ attribute. Yet, there will be no type checking at runtime. Checks have to be done via MyPy or other type checkers.

Let's use MyPy on the previous example:

%%writefile example.py
def greeting(name: str, phrase: str='Hello') -> str:
    return phrase + ' ' + name

print(greeting('Frank', 'Good evening'))
print(greeting('Olga'))

OUTPUT:

Overwriting example.py
!mypy example.py

OUTPUT:

Success: no issues found in 1 source file

Now a type annotation example with a type violation:

%%writefile example.py
def greeting(name: str, phrase: str='Hello') -> str:
    return phrase + ' ' + name

print(greeting('Frank', 42))

OUTPUT:

Overwriting example.py
!mypy example.py