PEP 3107 (annotations de fonction)

Bonjour à tous. J'ai décidé de bien comprendre les annotations Python et en même temps de traduire une série de PEP documentant ce sujet. Nous commencerons par les normes 3.X et terminerons par les innovations de python 3.8. Je dois dire tout de suite que ce PEP est l'un des plus basiques et sa lecture n'est utile qu'aux débutants. Eh bien, allons-y:


PEP 572 - Annotations de fonctions

Dynamisme3107
Titre:Annotations de fonction
Auteurs:Collin Winter <collinwinter at google.com>, Tony Lownds <tony at lownds.com>
Statut:Final
Un type:la norme
Créé:2-déc-2006
Version Python:3.0

Annotation à la norme


Ce PEP introduit une syntaxe pour ajouter des annotations arbitraires (métadonnées) aux fonctions en Python.

Justification


Les fonctions de Python 2.x n'avaient pas de méthode intégrée pour annoter les paramètres et renvoyer des valeurs. Pour combler cette lacune, de nombreux outils et bibliothèques sont apparus. Certains d'entre eux utilisent les décorateurs décrits dans PEP 318, tandis que d'autres analysent les fonctions de docstring et y recherchent des informations.

Ce PEP vise à fournir un moyen unique et standard d'annoter des fonctions afin de réduire la confusion qui a existé jusqu'à ce point, causée par la grande variation des mécanismes et de la syntaxe.

Principes de base de l'annotation des fonctionnalités


Avant de commencer à discuter des annotations des fonctionnalités de Python 3.0, parlons d'abord de leurs fonctionnalités en termes généraux:

  1. Les annotations pour les paramètres et les valeurs de retour des fonctions sont complètement facultatives.
  2. Les annotations ne sont rien d'autre qu'un moyen d'associer des expressions arbitraires à différentes parties d'une fonction au moment de la compilation.

    Python lui-même ne prête aucune attention aux annotations. La seule chose est qu'il vous permet d'y accéder, ce qui est décrit dans la section «Accès aux annotations de fonctionnalités» ci-dessous.

    Les annotations n'ont de sens que lorsqu'elles sont interprétées par des bibliothèques tierces. Ils peuvent faire ce qu'ils veulent avec des annotations de fonction. Par exemple, une bibliothèque peut utiliser des annotations de chaînes pour fournir des données de référence améliorées, par exemple:

    def compile(source: "something compilable",
                filename: "where the compilable thing comes from",
                mode: "is this a single statement or a suite?"):
        ...

    Une autre bibliothèque peut utiliser des annotations de fonction et de méthode Python pour vérifier la correspondance de type. Cette bibliothèque peut utiliser des annotations pour montrer quels types de données d'entrée elle attend et quel type de données elle renverra. Ce sera peut-être quelque chose comme ça:

    def haul(item: Haulable, *vargs: PackAnimal) -> Distance:
        ...

    Nous le répétons encore une fois: les annotations d' aucun des exemples en eux-mêmes n'ont de sens. Ils n'acquièrent un véritable sens qu'en combinaison avec des bibliothèques tierces.
  3. Comme il ressort du paragraphe 2, ce PEP n'essaie pas d'introduire de mécanisme standard pour le traitement des annotations, même pour les types intégrés. Tout ce travail est affecté à des bibliothèques tierces.

Syntaxe


Paramètres


Les annotations de paramètres sont des expressions facultatives qui suivent le nom du paramètre lui-même:

def foo (a: , b:  = 5):
    ...

En pseudogrammatique, les paramètres ressemblent maintenant à: paramètre [: expression] [= expression] . Autrement dit, les annotations, comme les valeurs par défaut, sont facultatives et précèdent toujours ces dernières. Tout comme un signe égal est utilisé pour indiquer une valeur par défaut, un deux-points est utilisé pour les annotations. Toutes les expressions d'annotation, comme les valeurs par défaut, sont évaluées lorsqu'une définition de fonction est exécutée. Obtenir des arguments "supplémentaires" (c'est-à-dire * args et ** kwargs) a la même syntaxe:

def foo(*args: expression, **kwargs: expression):
    ...

Les annotations pour les paramètres imbriqués suivent toujours le nom du paramètre, pas la dernière parenthèse. L'annotation de chaque «nom» dans le paramètre imbriqué n'est pas requise:

def foo((x1, y1: expression),
        (x2: expression, y2: expression)=(None, None)):
    ...

Valeurs de retour


Jusqu'à présent, nous n'avons pas fourni d'exemple sur la façon d'annoter le type de retour dans les fonctions. Cela se fait comme ceci:

def sum() -> expression:
    ...

Autrement dit, le littéral -> et une sorte d'expression peuvent maintenant suivre la liste des paramètres. Comme les annotations de paramètres, cette expression sera évaluée lors de l'exécution de la définition de fonction.

La grammaire complète des déclarations de fonctions est maintenant la suivante:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: ((tfpdef ['=' test] ',')*
                ('*' [tname] (',' tname ['=' test])* [',' '**' tname]
                 | '**' tname)
                | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
tname: NAME [':' test]
tfpdef: tname | '(' tfplist ')'
tfplist: tfpdef (',' tfpdef)* [',']

Lambdas


Les fonctions Lambda ne prennent pas en charge les annotations. Bien sûr, la syntaxe pourrait être corrigée en ajoutant la possibilité de "boucler" les arguments entre crochets, cependant, il a été décidé de ne pas effectuer une telle modification, car:

  1. Cela violerait la compatibilité descendante.
  2. Les lambdas sont neutres et anonymes par définition
  3. Les lambdas peuvent toujours être réécrits en tant que fonctions


Accédez aux annotations des fonctionnalités


Après la compilation, les annotations de fonction deviennent disponibles via l'attribut __annotations__. Cet attribut est un dictionnaire mutable comparant les noms des variables et les valeurs des annotations qui leur sont indiquées.

Le dictionnaire __annotations__ possède une touche spéciale "retour". Cette clé n'est présente que si une annotation a également été définie pour la valeur de retour de la fonction. Par exemple, l'annotation suivante:

def foo (a: 'x', b: 5 + 6, c: list) -> max (2, 9):
    ...

Sera retourné via l'attribut __annotations__ comme:

{'a': 'x',
 'b': 11,
 'c': list,
 'return': 9}

Le nom de clé «return» a été choisi car il ne peut pas entrer en conflit avec le nom du paramètre (toute tentative d'utilisation de return comme nom de paramètre entraînera une exception SyntaxError).

L'attribut __annotations__ sera vide si la fonction n'a pas d'annotations ou si la fonction a été créée via une expression lambda.

Cas d'utilisation


Au cours de la discussion des annotations, nous avons examiné plusieurs options pour leur utilisation. Certains d'entre eux sont présentés ici et regroupés en fonction de la "classe" des informations transmises. Vous trouverez également ici des exemples de produits et de packages existants qui peuvent utiliser des annotations.

  • Fournir des informations sur le type
    • Vérification de type
    • Conseils IDE sur les types d'arguments attendus et retournés
    • Surcharge de fonctions / fonctions génériques [env. la surcharge de fonctions est populaire dans d'autres langages et consiste en l'existence de plusieurs fonctions avec les mêmes noms, mais en même temps, le nombre de paramètres acceptés par eux varie]
    • Des ponts entre différents langages de programmation
    • Adaptation
    • Fonctions logiques de prédicat
    • Mappage d'une requête de base de données
    • Marshaling des paramètres RPC [env. Le marshaling est le processus de conversion des informations stockées dans la RAM dans un format adapté au stockage ou à la transmission. RPC - Appel de procédure à distance]
  • Fournir d'autres informations
    • Documentation des paramètres et des valeurs de retour

Bibliothèque standard


Pydoc et inspecter les modules


Le module pydoc affichera des annotations dans les informations de référence de la fonction. Le module d'inspection changera et prendra en charge les annotations.

Lien avec d'autres PEP


Objets de signature de fonction


Les objets de signature de fonction doivent fournir des annotations de fonction. L'objet de paramètre et d'autres choses peuvent changer. [environ. Signature (Signature) de la fonction - partie de sa déclaration générale, permettant aux moyens de traduction d'identifier la fonction entre autres]

la mise en oeuvre


L'implémentation de référence a été incluse dans la branche py3k (anciennement «p3yk») en tant que révision 53170

Offres refusées


  • BDFL [. ] , , : « »
  • stdlib , , . .
  • , , .
  • Malgré de nouvelles discussions, il a été décidé de ne pas normaliser le mécanisme d'interaction des annotations. Un tel accord à ce stade serait prématuré. Nous voulons permettre à ces accords de se développer de manière organique, sur la base d'une situation réelle, et ne pas essayer de forcer tout le monde à utiliser une sorte de schéma artificiel.

All Articles