Les autres réponses ont bien expliqué le typage du canard et la réponse simple par tzot :
Python n'a pas de variables, comme d'autres langages où les variables ont un type et une valeur; il a des noms pointant vers des objets qui connaissent leur type.
Cependant , une chose intéressante a changé depuis 2010 (lorsque la question a été posée pour la première fois), à savoir l'implémentation de PEP 3107 (implémenté en Python 3). Vous pouvez maintenant réellement spécifier le type d'un paramètre et le type du type de retour d'une fonction comme ceci:
def pick(l: list, index: int) -> int:
return l[index]
Nous pouvons voir ici que cela pick
prend 2 paramètres, une liste l
et un entier index
. Il doit également renvoyer un entier.
Il s'agit donc ici d' l
une liste d'entiers que nous pouvons voir sans trop d'effort, mais pour des fonctions plus complexes, cela peut être un peu déroutant quant à ce que la liste doit contenir. Nous voulons également que la valeur par défaut index
soit 0. Pour résoudre ce problème, vous pouvez choisir d'écrire pick
comme ceci à la place:
def pick(l: "list of ints", index: int = 0) -> int:
return l[index]
Notez que nous mettons maintenant une chaîne comme type de l
, ce qui est autorisé syntaxiquement, mais ce n'est pas bon pour l'analyse par programme (que nous reviendrons plus tard).
Il est important de noter que Python n'augmentera pas TypeError
si vous passez un flotteur index
, la raison en est l'un des principaux points de la philosophie de conception de Python: "Nous sommes tous des adultes consentants ici" , ce qui signifie que vous êtes censé soyez conscient de ce que vous pouvez passer à une fonction et de ce que vous ne pouvez pas. Si vous voulez vraiment écrire du code qui lance TypeErrors, vous pouvez utiliser la isinstance
fonction pour vérifier que l'argument passé est du type approprié ou d'une sous-classe de celui-ci comme ceci:
def pick(l: list, index: int = 0) -> int:
if not isinstance(l, list):
raise TypeError
return l[index]
Plus d'informations sur les raisons pour lesquelles vous devriez rarement faire cela et sur ce que vous devriez faire à la place sont discutées dans la section suivante et dans les commentaires.
Le PEP 3107 améliore non seulement la lisibilité du code, mais propose également plusieurs cas d'utilisation appropriés que vous pouvez lire ici .
L'annotation de type a attiré beaucoup plus d'attention dans Python 3.5 avec l'introduction de PEP 484 qui introduit un module standard pour les indications de type.
Ces indices de type provenaient du vérificateur de type mypy ( GitHub ), qui est maintenant conforme au PEP 484 .
Avec le module de frappe est livré avec une collection assez complète d'indices de type, y compris:
List
, Tuple
, Set
, Map
- pour list
, tuple
, set
et map
respectivement.
Iterable
- utile pour les générateurs.
Any
- quand ça pourrait être n'importe quoi.
Union
- quand il pourrait être n'importe quoi dans un ensemble spécifié de types, par opposition à Any
.
Optional
- quand ce pourrait être Aucun. Sténographie pour Union[T, None]
.
TypeVar
- utilisé avec des génériques.
Callable
- utilisé principalement pour les fonctions, mais pourrait être utilisé pour d'autres callables.
Ce sont les indices de type les plus courants. Une liste complète se trouve dans la documentation du module de saisie .
Voici l'ancien exemple utilisant les méthodes d'annotation introduites dans le module de frappe:
from typing import List
def pick(l: List[int], index: int) -> int:
return l[index]
Une fonctionnalité puissante est la Callable
qui vous permet de taper des méthodes d'annotation qui prennent une fonction en argument. Par exemple:
from typing import Callable, Any, Iterable
def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
"""An immediate version of map, don't pass it any infinite iterables!"""
return list(map(f, l))
L'exemple ci-dessus pourrait devenir plus précis avec l'utilisation de TypeVar
au lieu de Any
, mais cela a été laissé au lecteur car je pense avoir déjà rempli ma réponse avec trop d'informations sur les merveilleuses nouvelles fonctionnalités activées par l'indication de type.
Auparavant, lorsque l'on documentait du code Python avec par exemple Sphinx, certaines des fonctionnalités ci-dessus pouvaient être obtenues en écrivant des docstrings formatés comme ceci:
def pick(l, index):
"""
:param l: list of integers
:type l: list
:param index: index at which to pick an integer from *l*
:type index: int
:returns: integer at *index* in *l*
:rtype: int
"""
return l[index]
Comme vous pouvez le voir, cela prend un certain nombre de lignes supplémentaires (le nombre exact dépend de la façon dont vous voulez être explicite et de la façon dont vous formatez votre docstring). Mais il devrait maintenant être clair pour vous que le PEP 3107 fournit une alternative qui est à bien des égards (toutes?) Supérieure. Cela est particulièrement vrai en combinaison avec PEP 484 qui, comme nous l'avons vu, fournit un module standard qui définit une syntaxe pour ces types d'indications / annotations qui peut être utilisée de telle sorte qu'elle soit sans ambiguïté et précise mais flexible, ce qui en fait un combinaison puissante.
À mon avis, c'est l'une des meilleures fonctionnalités de Python. J'ai hâte que les gens commencent à en exploiter le pouvoir. Désolé pour la longue réponse, mais c'est ce qui se passe quand je m'excite.
Un exemple de code Python qui utilise fortement l'indication de type peut être trouvé ici .