Un monde typé qui commence par Python

A partir de Python 3.5, une fonctionnalité appelée Type Hints a été introduite.

Il s'agit d'une spécification qui vous permet d'ajouter des annotations de type (annotations de type), et ressemble spécifiquement à ce qui suit (Abstract Cité de 0484 / # abstract)).

def greeting(name: str) -> str:
    return 'Hello ' + name

La partie suivante est en fait une annotation.

Les indices de type mentionnent également les commentaires de type dans les déclarations de variables (https://www.python.org/dev/peps/pep-0484/#type-comments).

x = []   # type: List[Employee]

C'est vraiment une extension du commentaire, pas de la syntaxe, mais si vous commentez déjà ces types, vous pouvez détourner la notation ci-dessus et à l'avenir, vous pourrez faire la vérification de type avec un outil Il y a une possibilité.

C'est le monde typé qui a été introduit en Python.

L'annotation ajoutée n'est pas vérifiée lors de l'exécution. Bref, c'est une extension du commentaire. Par conséquent, il n'est pas exécutoire, mais il ne fait rien au moment de l'exécution et n'affecte pas les performances.

Par conséquent, en principe, la syntaxe est pour l'analyse statique, mais les informations d'annotation dans typing.get_type_hints Je pense qu'il est possible d'implémenter la vérification d'exécution par vous-même (par exemple, typeannotations).

Notation d'annotation

Je voudrais présenter la notation des annotations avec typage.

Type aliases

Il est possible de définir des alias de type.

Type aliases

Vector = List[float]

Cependant, d'après mon expérience personnelle, cela peut être déroutant (il est difficile de dire s'il s'agit d'une classe ou d'un alias), vous devez donc faire attention à l'endroit où vous l'utilisez et comment vous le nommez.

Callable

Ceci est un résumé des définitions d'argument de fonction / de type de retour. Il est utilisé lorsqu'une fonction est un argument comme une fonction de rappel, ou lorsqu'une fonction est renvoyée.

La notation est Callable ([type d'argument], type de retour). Voici un exemple d'annotation de feeder / async_query qui prend une fonction comme argument avec Callable.

Callable

from typing import Callable

def feeder(get_next_item: Callable[[], str]) -> None:
    # Body

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    # Body

Generics

Des soi-disant génériques sont également disponibles. Vous pouvez écrire List <T> en Java, etc. comme suit.

Generics

from typing import Sequence, TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

Vous pouvez également limiter les types valides de génériques avec TypeVar. Dans ce qui suit, seuls «str» et «bytes» sont autorisés comme AnyStr.

pep-0484/#generics

from typing import TypeVar

AnyStr = TypeVar('AnyStr', str, bytes)

def concat(x: AnyStr, y: AnyStr) -> AnyStr:
    return x + y

User-defined generic types

Si vous voulez faire quelque chose comme MyClass <T> dans la classe dite Generics, définissez-la comme suit.

User-defined generic types

from typing import TypeVar, Generic

T = TypeVar('T')

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value

    def set(self, new: T) -> None:
        self.log('Set ' + repr(self.value))
        self.value = new

    def get(self) -> T:
        self.log('Get ' + repr(self.value))
        return self.value

    def log(self, message: str) -> None:
        self.logger.info('{}: {}'.format(self.name message))

Vous pouvez maintenant l'utiliser comme ceci:

from typing import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

The Any type

Tous les types sont des sous-types de ʻAny. Notez que ʻAny est différent de ʻobject` dans la classe.

Union types

C'est une collection de plusieurs types acceptables. «Facultatif» est une sorte de cette «Union».

Union types

from typing import Union

def handle_employee(e: Union[Employee, None]) -> None: ...

C'est synonyme de:

from typing import Optional

def handle_employee(e: Optional[Employee]) -> None: ...

Méthode de vérification

Comme mentionné ci-dessus, je pense que la notation d'annotation de type couvre la plupart des scènes que vous souhaitez taper. Cependant, tel quel, c'est la même chose qu'un commentaire, et même si vous ignorez l'annotation que vous avez ajoutée, vous ne la remarquerez pas.

Le standard Python ne fournit pas d'outil officiel pour vérifier les annotations de type (à partir de 3.5). Par conséquent, vous devez utiliser un outil externe pour la vérification.

Un type de cet outil est «mypy».

mypy

Il a été développé par Jukka, qui est également l'auteur de typehinting de Python lui-même, et je pense que l'on peut dire que c'est la bibliothèque standard de facto pour les annotations de type.

Pour les vérifications dans l'environnement de développement intégré, PyCharm dispose d'un support. Dans ce qui suit, l'avertissement est l'endroit où une valeur numérique est transmise à salutation qui prend str comme argument.

image

PyCharm à l'origine prend en charge les annotations dans docstrings et les commentaires, et le support qui a repris le standard à l'avenir Je pense que vous pouvez vous attendre à ce que cela soit ajouté.

On dit que l'environnement de développement Python (PTVS) de Visual Studio est correct car il a à l'origine une forte inférence de type, mais il semble qu'il y ait un débat sur l'incorporation de la notation.

Use type hints in Python 3.x to infer variable types if possible #82

installer mypy

Ici, nous allons introduire la procédure d'introduction pour vérifier à l'aide de mypy.

Vous pouvez installer mypy depuis pip.

pip install mypy

~~ * Notez que pip install mypy comprendra une bibliothèque complètement différente ~~ De mypy 0.470, le nom de la bibliothèque a été changé de mypy-lang à mypy

Bien sûr, il est basé sur Python 3 (c'est ok même si ce n'est pas 3.5), mais [Python 2 sera également pris en charge](http://mypy.readthedocs.org/en/latest/faq.html#all-of-my-code -est-toujours-en-python-2-quelles-sont-mes-options). Depuis le 2 novembre 2015, si vous souhaitez utiliser mypy avec Python 3.5, vous devez l'installer à partir de master. Ceci est dû au fait que le support de ʻUndefined`, qui a été supprimé dans Python 3.5, n'a pas encore été reflété dans pypi (issue 639. ).

Pour pip installer à partir du maître GitHub, procédez comme suit:

pip install git+https://github.com/JukkaL/mypy.git@master

Utilisation de mypy

C'est selon le [Quick Start] officiel (https://github.com/JukkaL/mypy#quick-start), mais vous pouvez le vérifier avec la commande mypy qui sera disponible après l'installation.

mypy PROGRAM

Si cela ne fonctionne pas, veuillez vous référer à Dépannage. Les bases sont couvertes ici.

Lorsque vous l'exécutez réellement, le résultat de l'exécution sera le suivant.

>>> mypy examples/basic.py
examples\basic.py:5: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"

Vous pouvez également spécifier le module avec l'option -m.

>>> mypy -m examples
examples\__init__.py:1: note: In module imported here:
examples\basic.py:5: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"

Ici, «exemples / __ init __. Py» se présente comme suit.

import examples.basic

Comme l'indique la vérification "ʻIn module importé ici: ", lors du ciblage de paquets, il semble que tout ce qui ne suit pas de __init __. Py` n'est pas vérifié. Soyez donc prudent si vous souhaitez vérifier tous les fichiers d'un module.

Comme pour les bibliothèques existantes, il n'est pas possible d'annoter le code source du contenu et de faire le tour, il est donc également possible de découper la définition de type vers l'extérieur et de la définir. Un fichier qui décrit uniquement cette définition de type est appelé un fichier stub, et son extension est pyi (image TypeScript d.ts).

Si vous voulez lire le fichier pyi préparé par mypy, définissez MYPYPATH.

export MYPYPATH=~/work/myproject/stubs

Si vous utilisez l'option --use-python-path, celles de PYTHONPATH seront référencées.

Actuellement, il n'existe pas d'outil de gestion de définition de type comme tsd dans TypeScript, mais [python / typeshed](https: // github. Il semble que l'agrégation soit en cours sur com / python / typeshed) (bien qu'il n'y en ait pas encore beaucoup).

Pour plus de détails, veuillez vous référer au Document officiel.

Politique d'introduction

Les points suivants peuvent être attendus comme effets de l'introduction de TypeHints.

Et je pense que les objectifs applicables sont à peu près les suivants.

Les modèles suivants peuvent être considérés comme la méthode d'introduction d'annotations pour la cible spécifiée.

Lors de son introduction, je pense qu'il est nécessaire de préciser d'abord le type d'avantages que vous attendez. Si cela n'est pas clair, les critères d'application et de mise en œuvre seront ambigus.

Ce domaine fait l'objet d'essais et d'erreurs, notamment si l'effet attendu peut être obtenu en premier lieu, je voudrais donc l'ajouter lorsque j'aurai accumulé un savoir-faire.

Matériel de référence

Recommended Posts

Un monde typé qui commence par Python
[Python] Un programme qui crée des escaliers avec #
Faites une loterie avec Python
Un serveur qui fait écho aux données POSTées avec flask / python
Un mémo que j'ai touché au magasin de données avec python
Créer un répertoire avec python
Python commençant par Hello world!
Un mémo qui lit les données de dashDB avec Python et Spark
Utilisez une macro qui s'exécute lors de l'enregistrement de python avec vscode
Résoudre ABC163 A ~ C avec Python
Faites fonctionner l'imprimante de reçus avec python
Manuel de graphisme Python avec Matplotlib.
Faisons une interface graphique avec python.
Résoudre ABC166 A ~ D avec Python
Créez un environnement virtuel avec Python!
J'ai fait une loterie avec Python.
Créer un environnement virtuel avec Python 3
Résoudre ABC168 A ~ C avec Python
[Note] Sortie Hello world avec python
[Python] Générer un mot de passe avec Slackbot
Résoudre ABC162 A ~ C avec Python
Résoudre ABC167 A ~ C avec Python
Résoudre ABC158 A ~ C avec Python
Faisons un graphe avec python! !!
[Python] Hériter d'une classe avec des variables de classe
J'ai créé un démon avec Python
Ecrire un script batch avec Python3.5 ~
[Python] Créez un graphique qui peut être déplacé avec Plotly
J'ai fait un package qui peut comparer des analyseurs morphologiques avec Python
Je souhaite utiliser un caractère générique que je souhaite décortiquer avec Python remove
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai fait un shuffle qui peut être réinitialisé (inversé) avec Python
L'histoire de la création d'un module qui ignore le courrier avec python
[Pyenv] Construire un environnement python avec ubuntu 16.04
Livre en spirale en Python! Python avec un livre en spirale! (Chapitre 14 ~)
Créer un décorateur de fonction Python avec Class
Créer un fichier power simple avec Python
Faisons un jeu de shiritori avec Python
Installer Python en tant que Framework avec pyenv
J'ai fait un compteur de caractères avec Python
[Python] Dessiner un motif de tourbillon avec une tortue
J'ai dessiné une carte thermique avec Seaborn [Python]
[Python] Créez un environnement virtuel avec Anaconda
Créons un groupe gratuit avec Python
Un mémo contenant Python2.7 et Python3 dans CentOS
Création d'un environnement Python 3.6 avec Windows + PowerShell
Carte des informations de location sur une carte avec python
Rechercher le labyrinthe avec l'algorithme python A *
Faisons la voix lentement avec Python
Créé un voyage de fléchettes avec python (news)
[Python] Une application web rapide avec Bottle!
[AtCoder] Résoudre ABC1 ~ 100 Un problème avec Python
Ecrire un client TCP avec Python Twisted
Ce que j'ai fait avec les tableaux Python
Résoudre AtCoder ABC168 avec python (A ~ D)
Créer un compteur de fréquence de mots avec Python 3.4
Essayez le scraping HTML avec la bibliothèque Python
Visualisez le point P qui fonctionne avec Python