Back to main.

Calmcode Shorts

typeguard.py logotypeguard.py

In this short we're going to discuss the typechecked decorator in the typeguard project. The tool can be installed via pip.

pip install typeguard

Let's say we take the function below as an example.

def investment_return(start: float, interest: float, years: float) -> float:
    """Amount on the bank given an interest rate and time"""
    return round(start * (interest**years), 2)

This function works, but the type information that has been added isn't directly enforced. This means that if a user passes a wrong type into a function that we may not get a meaningful error message unless we do something like:

def investment_return(start: float, interest: float, years: float) -> float:
    """Amount on the bank given an interest rate and time"""
    if not isinstance(start, float):
        raise ValueError("wrong type for `start`~")
    return round(start * (interest**years), 2)

This technically works, but you'll need to do this for all the types in the function which can become quite a burden. So instead, we're going to use a decorator to handle this for us.

from typeguard import typechecked

@typechecked
def investment_return(start: float, interest: float, years: float) -> float:
    """Amount on the bank given an interest rate and time"""
    return round(start * (interest**years), 2)

The @typechecked decorator will make sure that appropriate errors get raised when a user passes variables of the wrong type.

Classes

What's especially nice about the @typechecked decorator is that it also works on classes. It understands classes that you've created and it can also check all the type information used in all the methods of a class.

This is example used in the video to demonstrate this effect.

from typeguard import typechecked

@typechecked
class Animal:
    def __init__(self, kind: str, sound: str):
        self.kind = kind
        self.sound = sound

@typechecked
class Utilities:
    def __init__(self, animal: Animal):
        self.animal = animal

    def repeat_sound(self, n_times: int = 1):
        return (self.animal.sound + "!") * n_times

dog = Animal(kind="dog", sound="woof")
utils = Utilities(animal=dog)
utils.repeat_sound(3)

Back to main.