Annotations de fonction: PEP-3107
Je suis tombé sur un extrait de code démontrant les annotations de fonction de Python3. Le concept est simple mais je ne vois pas pourquoi ceux-ci ont été implémentés dans Python3 ou leurs bonnes utilisations. Peut-être que SO peut m'éclairer?
Comment ça fonctionne:
def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
... function body ...
Tout ce qui suit les deux points après un argument est une «annotation», et les informations qui suivent ->
sont une annotation pour la valeur de retour de la fonction.
foo.func_annotations renverrait un dictionnaire:
{'a': 'x',
'b': 11,
'c': list,
'return': 9}
Quelle est la signification d'avoir cela disponible?
python
function
annotations
python-3.x
Agscala
la source
la source
foo.func_annotations
êtrefoo.__annotations__
en python3?def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
dire?Réponses:
Je pense que c'est vraiment génial.
Issu d'un milieu universitaire, je peux vous dire que les annotations se sont révélées inestimables pour activer des analyseurs statiques intelligents pour des langages comme Java. Par exemple, vous pouvez définir des sémantiques telles que des restrictions d'état, des threads autorisés à accéder, des limitations d'architecture, etc., et il existe de nombreux outils qui peuvent ensuite les lire et les traiter pour fournir des assurances au-delà de ce que vous obtenez des compilateurs. Vous pouvez même écrire des choses qui vérifient les conditions préalables / postconditions.
Je pense que quelque chose comme cela est particulièrement nécessaire en Python en raison de son typage plus faible, mais il n'y avait vraiment aucune construction qui rendait cela simple et faisait partie de la syntaxe officielle.
Il existe d'autres utilisations des annotations qui ne sont pas assurées. Je peux voir comment je pourrais appliquer mes outils basés sur Java à Python. Par exemple, j'ai un outil qui vous permet d'assigner des avertissements spéciaux aux méthodes, et qui vous donne des indications lorsque vous les appelez que vous devez lire leur documentation (par exemple, imaginez que vous avez une méthode qui ne doit pas être invoquée avec une valeur négative, mais c'est pas intuitif du nom). Avec des annotations, je pourrais technicall écrire quelque chose comme ça pour Python. De même, un outil qui organise des méthodes dans une grande classe basée sur des balises peut être écrit s'il existe une syntaxe officielle.
la source
Les annotations de fonction sont ce que vous en faites.
Ils peuvent être utilisés pour la documentation:
Ils peuvent être utilisés pour le contrôle de pré-condition:
Voir également http://www.python.org/dev/peps/pep-0362/ pour un moyen d'implémenter la vérification de type.
la source
Mass
et à laVelocity
place.def kinetic_energy(mass: 'in kilograms', velocity: 'in meters per second') -> float:
également montrer le type de retour. C'est ma réponse préférée ici.return
annotation? Il ne semble pas apparaître danslocals
C'est une réponse tardive, mais AFAICT, la meilleure utilisation actuelle des annotations de fonction est PEP-0484 et MyPy .
Utilisé comme ça:
la source
list(fib('a'))
avec votre exemple de fonction, Python 3.7 accepte volontiers l'argument et se plaint qu'il n'y a aucun moyen de comparer une chaîne et un int.Juste pour ajouter un exemple spécifique d'une bonne utilisation de ma réponse ici , couplé avec des décorateurs, un mécanisme simple pour plusieurs méthodes peut être fait.
et un exemple d'utilisation:
Cela peut être fait en ajoutant les types au décorateur comme le montre le post original de Guido , mais annoter les paramètres eux-mêmes est préférable car cela évite la possibilité d'une mauvaise correspondance des paramètres et des types.
Remarque : en Python, vous pouvez accéder aux annotations au
function.__annotations__
lieu defunction.func_annotations
lafunc_*
suppression du style sur Python 3.la source
function = self.typemap.get(types)
ne pas fonctionner lorsque des sous-classes sont impliquées. Dans ce cas, vous devrez probablement boucler entypemap
utilisantisinnstance
. Je me demande si@overload
cela gère correctement__annotations__
est undict
qui n'assure pas l'ordre des arguments, donc cet extrait de code échoue parfois. Je recommanderais de changer letypes = tuple(...)
àspec = inspect.getfullargspec(function)
alorstypes = tuple([spec.annotations[x] for x in spec.args])
.Uri a déjà donné une réponse correcte, alors voici une réponse moins sérieuse: vous pouvez donc raccourcir vos docstrings.
la source
La première fois que j'ai vu des annotations, je me suis dit "génial! Enfin, je peux opter pour une vérification de type!" Bien sûr, je n'avais pas remarqué que les annotations ne sont pas réellement appliquées.
J'ai donc décidé d' écrire un simple décorateur de fonctions pour les appliquer :
Je l'ai ajouté à la bibliothèque Ensure .
la source
Cela fait longtemps que cela n'a pas été posé, mais l'exemple d'extrait de code donné dans la question est (comme indiqué ici également) de PEP 3107 et à la fin de cet exemple de PEP Des cas d'utilisation sont également donnés qui pourraient répondre à la question du point de PEP de vue ;)
Ce qui suit est cité de PEP3107
Cas d'utilisation
Au cours de la discussion des annotations, un certain nombre de cas d'utilisation ont été soulevés. Certains d'entre eux sont présentés ici, regroupés en fonction du type d'informations qu'ils véhiculent. Sont également inclus des exemples de produits et packages existants qui pourraient utiliser des annotations.
Voir le PEP pour plus d'informations sur des points spécifiques (ainsi que leurs références)
la source
Python 3.X (uniquement) généralise également la définition de fonction pour permettre aux arguments et aux valeurs de retour d'être annotés avec des valeurs d'objet à utiliser dans les extensions .
Ses données META à expliquer, pour être plus explicite sur les valeurs de fonction.
Les annotations sont codées comme
:value
après le nom de l'argument et avant une valeur par défaut, et comme->value
après la liste d'arguments.Ils sont collectés dans un
__annotations__
attribut de la fonction, mais ne sont pas traités autrement comme spéciaux par Python lui-même:EXEMPLE:
Le
typeannotations
module fournit un ensemble d'outils pour la vérification de type et l'inférence de type du code Python. Il fournit également un ensemble de types utiles pour annoter des fonctions et des objets.Ces outils sont principalement conçus pour être utilisés par des analyseurs statiques tels que les linters, les bibliothèques de complétion de code et les IDE. De plus, des décorateurs pour effectuer des contrôles d'exécution sont fournis. La vérification de type à l'exécution n'est pas toujours une bonne idée en Python, mais dans certains cas, elle peut être très utile.
https://github.com/ceronman/typeannotations
Comment la saisie aide à écrire un meilleur code
PEP 526 - Syntaxe des annotations de variables
https://www.python.org/dev/peps/pep-0526/
https://www.attrs.org/en/stable/types.html
la source
Malgré toutes les utilisations décrites ici, la seule utilisation exécutoire et, très probablement, forcée des annotations sera pour les indices de type .
Cela n'est actuellement pas appliqué en aucune façon mais, à en juger par PEP 484, les futures versions de Python n'autoriseront que les types comme valeur pour les annotations.
Citations Qu'en est-il des utilisations existantes des annotations? :
Bien que je n'ai pas encore vu de dépréciations silencieuses dans la version 3.6, cela pourrait très bien être ramené à 3.7 à la place.
Ainsi, même s'il peut y avoir d'autres bons cas d'utilisation, il est préférable de les garder uniquement pour les indications de type si vous ne voulez pas tout changer dans un futur où cette restriction est en place.
la source
En guise de réponse un peu retardée, plusieurs de mes packages (marrow.script, WebCore, etc.) utilisent des annotations lorsqu'elles sont disponibles pour déclarer le typage (c.-à-d. Transformer les valeurs entrantes du Web, détecter quels arguments sont des commutateurs booléens, etc.). comme pour effectuer un balisage supplémentaire des arguments.
Marrow Script crée une interface de ligne de commande complète vers des fonctions et des classes arbitraires et permet de définir la documentation, la conversion et les valeurs par défaut dérivées du rappel via des annotations, avec un décorateur pour prendre en charge les anciens environnements d'exécution. Toutes mes bibliothèques qui utilisent des annotations prennent en charge les formulaires:
La prise en charge «nue» des docstrings ou des fonctions de transtypage permet un mixage plus facile avec d'autres bibliothèques prenant en charge les annotations. (C'est-à-dire avoir un contrôleur Web utilisant la conversion de type qui se trouve également être exposé en tant que script de ligne de commande.)
Modifié pour ajouter: J'ai également commencé à utiliser le package TypeGuard en utilisant des assertions de développement pour la validation. Avantage: lors de l'exécution avec les "optimisations" activées (
-O
/PYTHONOPTIMIZE
env var) les vérifications, qui peuvent être coûteuses (par exemple récursives) sont omises, avec l'idée que vous avez correctement testé votre application en développement, donc les vérifications devraient être inutiles en production.la source
Les annotations peuvent être utilisées pour moduler facilement le code. Par exemple, un module pour un programme que je gère pourrait simplement définir une méthode comme:
et nous pourrions demander à l'utilisateur une chose nommée "param1" qui est "Nécessaire pour compter" et devrait être un "int". En fin de compte, nous pouvons même convertir la chaîne donnée par l'utilisateur dans le type souhaité pour obtenir l'expérience la plus simple possible.
Consultez notre objet de métadonnées de fonction pour une classe open source qui aide avec cela et peut récupérer automatiquement les valeurs nécessaires et les convertir en n'importe quel type souhaité (car l'annotation est une méthode de conversion). Même les IDE affichent correctement la saisie semi-automatique et supposent que les types sont conformes aux annotations - un ajustement parfait.
la source
Si vous regardez la liste des avantages de Cython, l'un des principaux est la possibilité d'indiquer au compilateur le type d'un objet Python.
Je peux envisager un avenir où Cython (ou des outils similaires qui compilent une partie de votre code Python) utiliseront la syntaxe d'annotation pour faire leur magie.
la source
multiply
fonction à ne travailler que sur des nombres entiers, quand'na' * 8 + ' batman!'
est-il entièrement valide? ;)