← Retourner à la liste des articles
Image blog
Auteur

Par Maxime Jumelle

CTO & Co-Founder

Publié le 11 déc. 2020

Catégorie Machine Learning

Les annotations de fonctions Python

C'est quelque chose de bien connu : sous Python, pas besoin de spécifier les types des variables. Cette flexibilité permet de convertir très facilement des variables, ce qui est souvent le cas lorsque l'on manipule des données.

En revanche, lorsque l'on défini des fonctions, on aimerait insister sur le fait que certains paramètres soient d'un certain type, pour éviter des incohérences, voir des erreurs dans la suite du programme. Pour faciliter la lecture et la documentation des fonctions, la PEP 3107 autorise l'annotation des types des paramètres d'une fonction. Voyons en détail comment cela fonctionne.

Les annotations de fonctions

Prenons la fonction longueur qui va calculer la longueur d'une chaîne de caractère.

def longueur(x):
  return len(x)

longueur("Hello !")

Cette fonction requiert le paramètre x qui est une chaîne de caractères, et retourne un entier qui correspond à la longueur de cette même chaîne.


À lire aussi : découvrez notre formation MLOps


Comment spécifier ces deux types ? C'est là que les annotations de fonctions interviennent. Chaque paramètre va être suivi de son type, et la nous allons pouvoir spécifier la type retourné par la fonction avec ->.

def longueur(x: str) -> int:
  return len(x)

longueur("Hello !")

Cette fonction se lit : on s'attends à avoir un x de type chaîne de caractères, et retourne un entier.

L'avantage de cette représentation, c'est que cela est beaucoup plus clair sur le type attendu par la fonction, puisque en un coup d'oeil, on sait exactement quels types doivent être passés en argument.

Attention néamoins, et comme défini dans la PEP, l'annotation de fonctions est optionnelle : même si lors de l'appel de la fonction, le paramètre n'est pas du même type que celui inscrit dans la définition, Python ne générera pas d'erreurs.

longueur([-1, 2, 3, 4])

Ce que cela signifie, c'est que c'est à la charge du développeur de vérifier que les types des paramètres sont bien conformes.

def longueur(x: str) -> int:
  if not isinstance(x, str):  # isistance retourne Faux si le paramètre x n'est pas une chaîne de caractère
    return "Erreur ! Pas un str"
  return len(x)

print(longueur("Hello !"))
print(longueur([-1, 2, 3, 4]))

Ainsi, avec des vérifications de type comme la fonction isinstance, il faudra toujours vérifier le type des paramètres dans le cadre d'exécution d'une fonction critique. Les annotations de fonctions sont purement à titre d'amélioration de la lisibilité du code.

Notons, au passage, qu'il y a beaucoup de types prêt-à-l'emploi dans les annotations de fonctions :

  • str, int, float pour les types classiques.
  • List, Tuple, Set, Map pour les listes, tuples, ensembles and maps.
  • Iterable pour les itérateurs.
  • Union pour spécifier plusieurs types possibles.
  • Optional équivalent à Union[T, None].
  • Callable pour les fonctions en paramètres.
  • Any pour n'importe quel type.

Par exemple, la fonction suivante va appliquer une autre fonction f à chaque élément d'un itérable (comme une liste).

from typing import Callable, Any, Iterable, List

def vectorize(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
  output = []
  for elem in l:
    output.append(f(elem))
  return output

Comment s'interprète ces annotations ?

  • Tout d'abord, on s'attend à ce que f soit un callable (une fonction). Le type Callable nécessite deux informations : la liste des types des paramètres, et le type retourné. Ici, il n'y a qu'un seul paramètre donc le type est quelconque, matérialisé par [Any]. Le type retourné par la fonction f est lui aussi Any.
  • Ensuite, la second argument l doit être itérable (liste, générateur, ...) dont les éléments sont de n'improte quel type.
  • Enfin, la résultat retourné est de type List[Any], c'est-à-dire une liste Python dont les éléments sont de type quelconque.

À lire aussi : découvrez notre formation MLOps


Testons maintenant cette fonction.

def carre(x):
  return x * x

def lettre(x):
  return ['a', 'b', 'c', 'd', 'e'][x - 1]

liste = [1, 2, 3, 4, 5]

print(vectorize(carre, liste))
print(vectorize(lettre, liste))

Les deux appels à la fonction vectorize produisent le résultat attendu.

❓ Quel est donc l'intérêt d'annoter les fonctions ?

Le principal intérêt, comme évoqué plus haut, est la lisibilité du code. Lorsque l'on collabore à plusieurs sur un projet, il est important de bien comprendre le comportement de chaque fonction, qu'est-ce qui y est attendu et qu'est-ce qui est retourné comme résultat.

C'est encore plus le cas lorsque l'on travaille sur des projets Data où l'on manipule des données de natures très différentes (DataFrames, tenseurs, textes).

Vous souhaitez vous former au MLOps ?

Articles similaires

Blog

20 sept. 2022

Machine Learning

Hugging Face est une startup française qui s'est fait connaître grâce à l'infrastructure NLP qu'ils ont développée. Aujourd'hui, elle est sur le point de révolutionner le domaine du Machine Learning et traitement automatique du langage naturel. Dans cet article, nous allons présenter Hugging Face et détailler les taches de base que cette librairie permet de réaliser. Nous allons également énumérer ses avantages et ses alternatifs.

Nada Belaidi

Équipe Blent

Data Scientist

Lire l'article

Blog

12 juil. 2022

Machine Learning

spaCy est une bibliothèque open-source pour le traitement avancé du langage naturel. Elle est conçue spécifiquement pour une utilisation en production et permet de construire des applications qui traitent et comprennent de grands volumes de texte.

Nada Belaidi

Équipe Blent

Data Scientist

Lire l'article

Blog

4 juil. 2022

Machine Learning

Un auto-encodeur est une structure de réseaux neuronaux profonds qui s'entraîne pour réduire la quantité de données nécessaires pour représenter une donnée d'entrée. Ils sont couramment utilisés en apprentissage automatique pour effectuer des tâches de compression de données, d'apprentissage de représentations et de détection de motifs.

Nada Belaidi

Équipe Blent

Data Scientist

Lire l'article