PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Point rapide sur les types hints 6

lundi 27 avril 2015 à 11:57

Avec la 3.5 arrive les types hints.

Pour remettre ça dans le contexte, Python 3 avait introduit les functions annotations, c’est à dire la possibilité de rajouter une information aux paramètres et valeur de retour d’une fonction. Cette information pouvait être n’importe quel objet Python :

def add(a: "n'importe quel objet", b: 1) -> ImportError:
    return a + b

Ces annotations ne faisaient absolument rien à part être accessibles :

>>> add(1, 2)
3
>>> add.__annotations__
{'b': 1, 'a': "n'importe quel objet", 'return': <class 'ImportError'>}

Le but étant de permettre à la communauté de faire des propositions sur leur utilisation jusqu’à ce que la préférée soit retenue.

Aucune proposition n’a néanmoins autant de succès que de permettre optionnellement de déclarer le typage, et c’est donc ce processus qui est amorcé avec la prochaine version où l’on pourra faire :

def add(a: int, b: int) -> int:
    return a + b

Pour les cas plus complexes, un module contient des interfaces courantes. Par exemple, si votre fonction fait la somme d’un itérable :

from typing import Iterable
 
def total(l: Iterable):

Si vous voulez limiter l’itérable à un itérable d’entiers :

def total(l: Iterable[int]):

Pour les fonctions très complexes, ça peut vite devenir très, très moche :

def truc(l: Iterable[Tuple(Any(Bidule, Machin))], oui=True: bool, **kwargs) -> FuckIt:
    return FuckIt(l, oui, **kwargs)

Par ailleurs, le module typing va devenir une des rares bonnes raisons d’utiliser import * :)

La spec prévoit qu’on puisse mettre ces annotations dans un fichier séparé du code avec juste la signature des fonctions. D’un côté, ça a le bénéfice de permettre d’annoter un code inaltérable, ou en Python 2.7. D’un autre, le DRY va du coup aller se faire foutre et franchement, je code pas en Python pour avoir des headers comme en C.

L’implémentation originale ne fera strictement rien. Elle est juste là pour voir ce que les outils vont en faire : un IDE pourra facilement trouver une erreur de type, on pourra faire des hooks git qui vérifient qu’on n’a pas niqué notre code en balançant un mauvais type et pypy/cython/nuikta/numba vont pouvoir se rouler dans la boue des optimisations.

Cela veut dire que si j’ignore mon IDE et que je passe des arguments d’un type qui n’est pas annoté, Python l’exécutera quand même. Ouf.

Le bilan ?

Globalement positif.

C’est vrai que c’est méga moche. Et les propositions alternatives ne sont pas mieux.

Je rêve que les annotations dans les docstrings soient utilisées, mais Guido a dit niet pour des raisons que je trouve faiblement fondées : les dosctrings sont un format libre dur à parser et alors que la syntaxe Python est structurée, avec un bon lexer. L’argument avancé dans le PEP est carrément faible : les docstrings ça se fold dans tous les éditeurs, c’est tout l’avantage.

Perso, je pense que normaliser enfin le format des docstrings ne me parait pas une mauvaise chose. Et puis si on arrive à parser le HTML pourri qu’on trouve sur le Web, 3 lignes de docstrings, c’est pas la mer à boire.

Néanmoins c’est optionnel, souple, et la première implémentation ne se mouille pas trop, ce qui laisse de la marge pour corriger les problèmes qui vont forcément venir.

Le bénéfice potentiel est énorme.

D’un côté, on aura toujours un langage facile à apprendre et enseigner, le duck typing, l’exploration de code, le typage dynamique par défaut.

De l’autre, quand un surcroit de rigueur sera nécessaire, on pourra rajouter un filet de sécurité. Et dans quelques temps, peut-être même gagner sérieusement en perf.

Mais quand même, putain c’est moche.