Cours
L’interpréteur de Python permet d’effectuer une vérification des types. Comme Python est un langage dynamique, il n’impose pas de déclarer le type des objets ; cela peut entraîner des bugs et rendre les erreurs difficiles à repérer. Pour y remédier, on peut associer Python à divers outils et intégrer des fonctionnalités de typage statique, tout en profitant de son propre duck typing.
On distingue deux grandes familles de systèmes de types utilisées selon les langages, présentées ci-dessous.
- Langage à typage statique
- Langage à typage dynamique
Langage à typage statique
La vérification du type des variables s’effectue à la compilation. Le système de types impose également de déclarer explicitement le « type » d’une variable avant son utilisation. Parmi les langages à typage statique : Scala, Java, C++, etc.
Par exemple, la déclaration d’une chaîne de caractères en Scala est la suivante :var myCar:String = "Mercedes";
Ce code montre que la variable « myCar » est explicitement déclarée avec le type « String » et la valeur « Mercedes ».
Langage à typage dynamique
La vérification du type des variables s’effectue à l’exécution. Le système de types n’exige pas de déclaration explicite du « type » avant l’usage. Parmi les langages à typage dynamique : Python, JavaScript, Ruby, etc.
Par exemple, une chaîne en Python se déclare ainsi :myCar = "Mercedes"
Ici, la variable « myCar » n’a pas besoin d’être déclarée explicitement avec un type.
« type() » et « isinstance() » en Python
On peut connaître le type d’une variable avec la fonction native « type() ». Elle s’utilise à l’exécution, par exemple pour le débogage, afin d’identifier précisément les types manipulés. Observons le type de quelques variables dans l’exemple ci-dessous.
my_var = 12
print(type(my_var))
Le code ci-dessus affichera « int ». Le type de la variable étant un entier, « type() » permet de l’identifier.
La fonction « isinstance(obj, class) » de Python permet de savoir si « obj » (un objet) est une instance de la classe indiquée. La valeur renvoyée est booléenne : True ou False.
my_var = "Hello"
print(isinstance(my_var,str))
Le code ci-dessus renverra True. Le type de la variable étant une chaîne, « isinstance() » l’identifie correctement.
Duck typing en Python
Un principe bien connu en Python dit : « S’il ressemble à un canard, nage comme un canard et cancane comme un canard, alors c’est probablement un canard. » Autrement dit, le type d’un objet ou d’une classe importe moins que l’existence des méthodes et propriétés attendues ; si un objet expose des méthodes similaires, il peut être utilisé pour un usage donné.
Voyons un exemple pour clarifier ce point.
Considérons l’exemple suivant avec deux classes, « Duck » et « Human ». La classe Duck contient les méthodes « quack » et « fly ». De même, la classe Human définit ses propres méthodes « quack » et « fly ». Duck et Human sont deux classes différentes, donc des objets (types) différents. Toutefois, Human propose les mêmes méthodes « quack » et « fly » que Duck. On définit aussi une fonction « fly_quack », qui se rapproche plutôt du comportement d’un « Duck », puisqu’elle fait voler et cancaner l’objet reçu.
class Duck:
def quack(self):
print('Quack')
def fly(self):
print('Flap')
class Human:
def quack(self):
print('Trying to Quack like a duck')
def fly(self):
print('Spreading my arm to flap like a duck')
def fly_quack(thing):
thing.quack()
thing.fly()
Créons une instance de « Duck », « du », et passons-la à « fly_quack(du) ». Faisons de même avec une instance de « Human », « h », et appelons « fly_quack(h) ».
du = Duck()
fly_quack(du)
h = Human()
fly_quack(h)
La sortie du code ci-dessus est la suivante :
Trying to Quack like a duck
Spreading my arm to flap like a duck
Quack
Flap
Même si « Human » est une classe différente de « Duck », Python appelle bien la fonction « fly_quack » sur l’instance humaine. Les types d’objets diffèrent, mais comme « Human » expose des méthodes « quack » et « fly » similaires, il répond au contrat attendu.
Annotations de type et mypy
Les langages dynamiques comme Python favorisent la lisibilité et l’accessibilité du code, mais présentent aussi des limites. L’une d’elles tient à la détection tardive des erreurs d’exécution : Python n’imposant pas les types, des incohérences peuvent se glisser et devenir difficiles à traquer à mesure que la base de code grandit.
Depuis la version 3.5, Python prend en charge les annotations de type (Type Hints). Les versions antérieures peuvent ne pas les supporter.
Voici un exemple simple sans annotations de type ni mypy.
La fonction ci-dessous est censée effectuer une soustraction entre deux entiers et renvoyer le résultat.
def sub_this(x,y):
return 'Subtraction'
print(sub_this(8,'hello'))
Ici, la fonction devrait accepter deux entiers « x » et « y », mais en l’absence de contraintes, elle accepte n’importe quel type. De plus, la valeur de retour peut être arbitraire : une chaîne (« Subtraction ») est renvoyée alors qu’un entier était attendu.
Voyons maintenant une version similaire en utilisant des annotations de type et « mypy », afin d’introduire un contrôle statique des types et de réduire facilement erreurs et bugs.
« mypy » est un module Python de vérification statique des types, qui s’appuie sur le mécanisme dynamique de Python (duck typing) enrichi par les annotations de type.
Installez le paquet « mypy » :pip install mypy
Créez un fichier « mypy_example.py » en local et saisissez le code suivant.
Ce programme accepte deux entiers en paramètres et, après « -> », indique que la valeur de retour attendue est un « int ». Pourtant, la fonction renvoie une chaîne « Subtracted two integers ».
def sub_this(x:int,y:int) -> int:
return 'Subtracted two integers'
print(sub_this(8,4))
Exécutez la commande suivante dans votre terminal.
mypy mypy_example.py
Une erreur s’affichera, indiquant qu’une valeur de retour « str » inattendue a été trouvée, alors qu’un « int » est requis.

Modifions la fonction pour renvoyer la soustraction des deux entiers, de sorte qu’un entier soit bien retourné.
def sub_this(x:int,y:int) -> int:
return x - y
print(sub_this(8,4))

Le résultat montre un message de réussite : aucune anomalie détectée.
Félicitations
Félicitations, vous êtes arrivé au bout de ce tutoriel !
Dans ce tutoriel, vous avez découvert la vérification des types, les différents systèmes de types selon les langages, l’usage de « type() » et « isinstance() » en Python, le duck typing, ainsi que les annotations de type avec « mypy ».
Pour aller plus loin avec Python, découvrez le cours de DataCamp Software Engineering for Data Scientists in Python.
Références :