3. Type Annotations Decorators
By Bernd Klein. Last modified: 13 Jul 2023.
This chapter of our Python course is about decorators but only about how to annotate decorators with type annotations or type hints. If you want to learn all about decorators, we highly recommend our tutorials on Python decorators:
You will learn in this chapter how to annotate decorator functions, allowing you to enhance code readability and maintainability. We provide explanations of the syntax and demonstrate the benefits of using type annotations in your decorators.
Our first example will be a decorator for calling how often a function has been called.
You have to know a few things about the Jupyter-Notebooks cells (ipython shell) to understand how we save programs and start mypy
: With the shell magic %%writefile example1.py
we can write the content of a cell into a file with the name example1.py
.
In IPython syntax, the exclamation mark (!) allows users to run shell commands (from your operating system) from inside a Jupyter Notebook code cell. Simply start a line of code with ! and it will run the command in the shell. We use this to call mypy
on the Python file.
%%writefile example.py
from math import sin, cos
from typing import Callable
def call_counter(func: Callable) -> Callable:
def wrapper(*args, **kwargs):
wrapper.counter += 1
return func(*args, **kwargs)
setattr(wrapper, 'counter', 0)
# not possible:
setattr(wrapper, 'counter', 0)
return wrapper
sin = call_counter(sin)
cos = call_counter(cos)
@call_counter
def add(a: int, b: int) -> int:
return a + b
result = add(5, 3)
print(result)
print(sin(3.5))
print(sin(36.5))
print(getattr(sin, 'counter'))
OUTPUT:
Overwriting example.py
We can see that this Python code above works, if we let it run with Python:
!python example.py
OUTPUT:
8 -0.35078322768961984 -0.9317168878547055 2
We can also see that it works with mypy
as well:
!mypy example.py
OUTPUT:
Success: no issues found in 1 source file
The Future: PEP-612 with ParamSpec and Concatenate
%%writefile example.py
from typing import Callable, Any, Dict
def memoize(f: Callable) -> Callable:
memo: Dict[Any, Any] = {}
def helper(x: Any) -> Any:
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
def fib(n: int) -> int:
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
fib = memoize(fib)
fib(10)
OUTPUT:
Overwriting example.py
!mypy example.py
OUTPUT:
Success: no issues found in 1 source file
Live Python training
Upcoming online Courses
10 Mar 2025 to 14 Mar 2025
07 Apr 2025 to 11 Apr 2025
23 Jun 2025 to 27 Jun 2025
28 Jul 2025 to 01 Aug 2025
12 Mar 2025 to 14 Mar 2025
09 Apr 2025 to 11 Apr 2025
04 Jun 2025 to 06 Jun 2025
30 Jul 2025 to 01 Aug 2025
Efficient Data Analysis with Pandas
10 Mar 2025 to 11 Mar 2025
07 Apr 2025 to 08 Apr 2025
02 Jun 2025 to 03 Jun 2025
23 Jun 2025 to 24 Jun 2025
28 Jul 2025 to 29 Jul 2025
Machine Learning from Data Preparation to Deep Learning
10 Mar 2025 to 14 Mar 2025
07 Apr 2025 to 11 Apr 2025
02 Jun 2025 to 06 Jun 2025
28 Jul 2025 to 01 Aug 2025