6. Expressions

Ce chapitre explique la signification des éléments des expressions en Python.

Notes sur la syntaxe : dans ce chapitre et le suivant, nous utilisons la notation BNF étendue pour décrire la syntaxe, pas l’analyse lexicale. Quand une règle de syntaxe est de la forme

name ::=  othername

et qu’aucune sémantique n’est donnée, la sémantique de name est la même que celle de othername.

6.1. Conversions arithmétiques

Quand la description d’un opérateur arithmétique ci-dessous utilise la phrase « les arguments numériques sont convertis vers un type commun », cela signifie que l’implémentation de l’opérateur fonctionne de la manière suivante pour les types natifs :

  • Si l’un des deux arguments est du type nombre complexe, l’autre est converti en nombre complexe ;
  • sinon, si l’un des arguments est un nombre à virgule flottante, l’autre est converti en nombre à virgule flottante ;
  • sinon, les deux doivent être des entiers et aucune conversion n’est nécessaire.

Des règles supplémentaires s’appliquent pour certains opérateurs (par exemple, une chaîne comme opérande de gauche pour l’opérateur “%”). Les extensions doivent définir leurs propres règles de conversion.

6.2. Atomes

Les atomes sont les éléments de base des expressions. Les atomes les plus simples sont les identifiants et les littéraux. Les expressions entre parenthèses, crochets ou accolades sont aussi classées syntaxiquement comme des atomes. La syntaxe pour les atomes est :

atom      ::=  identifier | literal | enclosure
enclosure ::=  parenth_form | list_display | dict_display | set_display
               | generator_expression | yield_atom

6.2.1. Identifiants (noms)

Un identifiant qui apparaît en tant qu’atome est un nom. Lisez la section Identifiants et mots-clés pour la définition lexicale et la section Noms et liaisons pour la documentation sur les noms et les liaisons afférentes.

Quand un nom est lié à un objet, l’évaluation de l’atome produit cet objet. Quand le nom n’est pas lié, toute tentative de l’évaluer lève une exception NameError.

Transformation des noms privés : lorsqu’un identificateur qui apparaît textuellement dans la définition d’une classe commence par deux (ou plus) caractères de soulignement et ne se termine pas par deux (ou plus) caractères de soulignement, il est considéré comme un nom privé <private name> de cette classe. Les noms privés sont transformés en une forme plus longue avant que le code ne soit généré pour eux. La transformation insère le nom de la classe, avec les soulignés enlevés et un seul souligné inséré devant le nom. Par exemple, l’identificateur __spam apparaissant dans une classe nommée Ham est transformé en _Ham__spam. Cette transformation est indépendante du contexte syntaxique dans lequel l’identificateur est utilisé. Si le nom transformé est extrêmement long (plus de 255 caractères), l’implémentation peut le tronquer. Si le nom de la classe est constitué uniquement de traits de soulignement, aucune transformation n’est effectuée.

6.2.2. Littéraux

Python gère les littéraux de chaînes de caractères, de chaînes d’octets et de plusieurs autres types numériques :

literal ::=  stringliteral | bytesliteral
             | integer | floatnumber | imagnumber

L’évaluation d’un littéral produit un objet du type donné (chaîne de caractères, chaîne d’octets, entier, nombre à virgule flottante, nombre complexe) avec la valeur donnée. La valeur peut être approximée dans le cas des nombres à virgule flottante et des nombres imaginaires (complexes). Reportez-vous à la section Littéraux pour les détails.

Tous les littéraux sont de types immuables et donc l’identifiant de l’objet est moins important que sa valeur. Des évaluations multiples de littéraux avec la même valeur (soit la même occurrence dans le texte du programme, soit une autre occurrence) résultent dans le même objet ou un objet différent avec la même valeur.

6.2.3. Formes parenthésées

Une forme parenthésée est une liste d’expressions (cette liste est en fait optionnelle) placée à l’intérieur de parenthèses :

parenth_form ::=  "(" [starred_expression] ")"

Une liste d’expressions entre parenthèses produit ce que la liste de ces expressions produirait : si la liste contient au moins une virgule, elle produit un n-uplet (type tuple) ; sinon, elle produit l’expression elle-même (qui constitue donc elle-même la liste d’expressions).

Une paire de parenthèses vide produit un objet tuple vide. Comme les tuples sont immuables, la règle pour les littéraux s’applique (c’est-à-dire que deux occurrences du tuple vide peuvent, ou pas, produire le même objet).

Notez que les tuples ne sont pas créés par les parenthèses mais par l’utilisation de la virgule. L’exception est le tuple vide, pour lequel les parenthèses sont requises (autoriser que « rien » ne soit pas parenthésé dans les expressions aurait généré des ambigüités et aurait permis à certaines coquilles de passer inaperçu).

6.2.4. Agencements des listes, ensembles et dictionnaires

Pour construire une liste, un ensemble ou un dictionnaire, Python fournit des syntaxes spéciales dites « agencements » (displays en anglais), chaque agencement comportant deux variantes :

  • soit le contenu du conteneur est listé explicitement,
  • soit il est calculé à l’aide de la combinaison d’une boucle et d’instructions de filtrage, appelée une compréhension (dans le sens de ce qui sert à définir un concept, par opposition à extension).

Les compréhensions sont constituées des éléments de syntaxe communs suivants :

comprehension ::=  expression comp_for
comp_for      ::=  ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter     ::=  comp_for | comp_if
comp_if       ::=  "if" expression_nocond [comp_iter]

Une compréhension est constituée par une seule expression suivie par au moins une clause for et zéro ou plus clauses for ou if. Dans ce cas, les éléments du nouveau conteneur sont ceux qui auraient été produits si l’on avait considéré toutes les clauses for ou if comme des blocs, imbriqués de la gauche vers la droite, et évalué l’expression pour produire un élément à chaque fois que le bloc le plus imbriqué était atteint.

Cependant, à part l’expression de l’itérable dans la clause for la plus à gauche, la compréhension est exécutée dans une portée séparée, implicitement imbriquée. Ceci assure que les noms assignés dans la liste cible ne « fuient » pas en dehors de cette portée.

L’expression de l’itérable dans la clause for la plus à gauche est évaluée directement dans la portée englobante puis passée en tant qu’argument à la portée implicite imbriquée. Les clauses for suivantes et les filtres conditionnels de la clause for la plus à gauche ne peuvent pas être évalués dans la portée englobante car ils peuvent dépendre de valeurs obtenues à partir de l’itérable le plus à gauche. Par exemple : [x*y for x in range(10) for y in range(x, x+10)].

Pour assurer que le résultat de la compréhension soit un conteneur du type approprié, les expressions yield et yield from sont interdites dans la portée implicite imbriquée (dans Python 3.7, de telles expressions lèvent un DeprecationWarning à la compilation, dans Python 3.8 et suivants, elles lèveront une SyntaxError).

Depuis Python 3.6, dans une fonction async def, une clause async for peut être utilisée pour itérer sur un itérateur asynchrone. Une compréhension dans une fonction async def consiste alors à avoir une clause for or async for suivie par des clauses for or async for additionnelles facultatives et, possiblement, des expressions await. Si la compréhension contient soit des clauses async for, soit des expressions await, elle est appelée compréhension asynchrone. Une compréhension asynchrone peut susprendre l’exécution de la fonction coroutine dans laquelle elle apparaît. Voir aussi la PEP 530.

Nouveau dans la version 3.6: Les compréhensions asynchrones ont été introduites.

Obsolète depuis la version 3.7: yield et yield from sont obsolètes dans la portée implicite imbriquée.

6.2.5. Agencements de listes

Un agencement de liste est une suite (possiblement vide) d’expressions à l’intérieur de crochets :

list_display ::=  "[" [starred_list | comprehension] "]"

Un agencement de liste produit un nouvel objet liste, dont le contenu est spécifié soit par une liste d’expression soit par une compréhension. Quand une liste d’expressions (dont les éléments sont séparés par des virgules) est fournie, ces éléments sont évalués de la gauche vers la droite et placés dans l’objet liste, dans cet ordre. Quand c’est une compréhension qui est fournie, la liste est construite à partir des éléments produits par la compréhension.

6.2.6. Agencements d’ensembles

Un agencement d’ensemble (type set) est délimité par des accolades et se distingue de l’agencement d’un dictionnaire par le fait qu’il n’y a pas de « deux points » : pour séparer les clés et les valeurs :

set_display ::=  "{" (starred_list | comprehension) "}"

Un agencement d’ensemble produit un nouvel objet ensemble muable, le contenu étant spécifié soit par une séquence d’expression, soit par une compréhension. Quand une liste (dont les éléments sont séparés par des virgules) est fournie, ses éléments sont évalués de la gauche vers la droite et ajoutés à l’objet ensemble. Quand une compréhension est fournie, l’ensemble est construit à partir des éléments produits par la compréhension.

Un ensemble vide ne peut pas être construit par {} ; cette écriture construit un dictionnaire vide.

6.2.7. Agencements de dictionnaires

Un agencement de dictionnaire est une série (possiblement vide) de couples clés-valeurs entourée par des accolades :

dict_display       ::=  "{" [key_datum_list | dict_comprehension] "}"
key_datum_list     ::=  key_datum ("," key_datum)* [","]
key_datum          ::=  expression ":" expression | "**" or_expr
dict_comprehension ::=  expression ":" expression comp_for

Un agencement de dictionnaire produit un nouvel objet dictionnaire.

Si une séquence (dont les éléments sont séparés par des virgules) de couples clés-valeurs est fournie, les couples sont évalués de la gauche vers la droite pour définir les entrées du dictionnaire : chaque objet clé est utilisé comme clé dans le dictionnaire pour stocker la donnée correspondante. Cela signifie que vous pouvez spécifier la même clé plusieurs fois dans la liste des couples clés-valeurs et, dans ce cas, la valeur finalement stockée dans le dictionnaire est la dernière donnée.

Une double astérisque ** demande de dépaqueter le dictionnaire. L’opérande doit être un tableau de correspondances. Chaque élément du tableau de correspondances est ajouté au nouveau dictionnaire. Les valeurs les plus récentes remplacent les valeurs déjà définies par des couples clés-valeurs antérieurs ou par d’autres dépaquetages de dictionnaires antérieurs.

Nouveau dans la version 3.5: le dépaquetage peut se faire vers un agencement de dictionnaire, proposé à l’origine par la PEP 448.

Une compréhension de dictionnaire, au contraire des compréhensions de listes ou d’ensembles, requiert deux expressions séparées par une virgule et suivies par les clauses usuelles « for » et « if ». Quand la compréhension est exécutée, les éléments clés-valeurs sont insérés dans le nouveau dictionnaire dans l’ordre dans lequel ils sont produits.

Les restrictions relatives aux types des clés sont données dans la section Hiérarchie des types standards (pour résumer, le type de la clé doit être hachable, ce qui exclut tous les objets muables). Les collisions entre les clés dupliquées ne sont pas détectées ; la dernière valeur (celle qui apparaît le plus à droite dans l’agencement) stockée prévaut pour une clé donnée.

6.2.8. Générateurs (expressions)

Une expression générateur est une notation concise pour un générateur, entourée de parenthèses :

generator_expression ::=  "(" expression comp_for ")"

Une expression générateur produit un nouvel objet générateur. Sa syntaxe est la même que celle des compréhensions, sauf qu’elle est entourée de parenthèses au lieu de crochets ou d’accolades.

Les variables utilisées dans une expression générateur sont évaluées paresseusement, au moment où la méthode __next__() de l’objet générateur est appelée (de la même manière que pour les générateurs classiques). Cependant, l’expression de l’itérable dans la clause for la plus à gauche est immédiatement évaluée, de manière à ce qu’une erreur dans cette partie soit signalée à l’endroit où l’expression génératrice est définie plutôt qu’à l’endroit où la première valeur est récupérée. Les clauses for suivantes ne peuvent pas être évaluées dans la portée implicite imbriquée car elles peuvent dépendre de valeurs obtenues à partir de boucles for plus à gauche. Par exemple, (x*y for x in range(10) for y in range(x, x+10)).

Les parenthèses peuvent être omises pour les appels qui ne possèdent qu’un seul argument. Voir la section Appels pour les détails.

To avoid interfering with the expected operation of the generator expression itself, yield and yield from expressions are prohibited in the implicitly defined generator (in Python 3.7, such expressions emit DeprecationWarning when compiled, in Python 3.8+ they will emit SyntaxError).

Si une expression générateur contient une ou des expressions async for ou await, elle est appelée expression générateur asynchrone <asynchronous generator expression>. Une expression générateur asynchrone produit un nouvel objet générateur asynchrone qui est un itérateur asynchrone (voir Itérateurs asynchrones).

Nouveau dans la version 3.6: les expressions générateurs asynchrones ont été introduites.

Modifié dans la version 3.7: Avant Python 3.7, les expressions générateurs asynchrones ne pouvaient apparaître que dans les coroutines async def. À partir de la version 3.7, toute fonction peut utiliser des expressions générateurs asynchrones.

Obsolète depuis la version 3.7: yield et yield from sont obsolètes dans la portée implicite imbriquée.

6.2.9. Expressions yield

yield_atom       ::=  "(" yield_expression ")"
yield_expression ::=  "yield" [expression_list | "from" expression]

Une expression yield est utilisée pour définir une fonction générateur ou une fonction générateur asynchrone et ne peut donc être utilisée que dans le corps de la définition d’une fonction. L’utilisation d’une expression yield dans le corps d’une fonction entraîne que cette fonction devient un générateur et son utilisation dans le corps d’une fonction async def entraine que cette fonction coroutine devient un générateur asynchrone. Par exemple :

def gen():  # defines a generator function
    yield 123

async def agen(): # defines an asynchronous generator function (PEP 525)
    yield 123

En raison des effets de bords sur la portée contenant, les expressions yield ne sont pas autorisées dans la portée implicite utilisée dans l’implémentation des compréhensions et des expressions générateurs (dans Python 3.7, de telles expressions lèvent un DeprecationWarning à la compilation ; à partir de Python 3.8, elles lèveront une SyntaxError).

Obsolète depuis la version 3.7: Les expressions yield sont obsolètes dans la portée implicite imbriquée utilisée dans l’implémentation des compréhensions et des expressions générateurs.

Les fonctions générateurs sont décrites plus loin alors que les fonctions générateurs asynchrones sont décrites séparément dans la section Fonctions générateurs asynchrones.

Lorsqu’une fonction générateur est appelée, elle renvoie un itérateur que l’on appelle générateur. Ce générateur contrôle l’exécution de la fonction générateur. L’exécution commence lorsque l’une des méthodes du générateur est appelée. À ce moment, l’exécution se déroule jusqu’à la première expression yield, où elle se suspend, renvoyant la valeur de expression_list à l’appelant du générateur. Cette suspension conserve tous les états locaux, y compris les liaisons en cours des variables locales, le pointeur d’instruction, la pile d’évaluation interne et l’état de tous les gestionnaires d’exceptions. Lorsque l’exécution reprend en appelant l’une des méthodes du générateur, la fonction s’exécute exactement comme si l’expression yield n’avait été qu’un simple appel externe. La valeur de l’expression yield après reprise dépend de la méthode qui a permis la reprise de l’exécution. Si c’est __next__() qui a été utilisée (typiquement via un for ou la fonction native next()) alors le résultat est None. Sinon, si c’est send() qui a été utilisée, alors le résultat est la valeur transmise à cette méthode.

Tout ceci rend les fonctions générateurs très similaires aux coroutines : elles produisent plusieurs objets via des expressions yield, elles possèdent plus qu’un seul point d’entrée et leur exécution peut être suspendue. La seule différence est qu’une fonction générateur ne peut pas contrôler où l’exécution doit se poursuivre après une instruction yield ; ce contrôle est toujours du ressort de l’appelant au générateur.

Les expressions yield sont autorisées partout dans un bloc try. Si l’exécution du générateur ne reprend pas avant qu’il ne soit finalisé (parce que son compteur de référence est tombé à zéro ou parce qu’il est nettoyé par le ramasse-miettes), la méthode close() du générateur-itérateur est appelée, ce qui permet l’exécution de toutes les clauses finally en attente.

L’utilisation de yield from <expr> traite l’expression passée en paramètre comme un sous-itérateur. Toutes les valeurs produites par ce sous-itérateur sont directement passées à l’appelant des méthodes du générateur courant. Toute valeur passée par send() ou toute exception passée par throw() est transmise à l’itérateur sous-jacent s’il possède les méthodes appropriées. Si ce n’est pas le cas, alors send() lève une AttributeError ou une TypeError, alors que throw() ne fait que propager l’exception immédiatement.

Quand l’itérateur sous-jacent a terminé, l’attribut value de l’instance StopIteration qui a été levée devient la valeur produite par l’expression yield. Elle peut être définie explicitement quand vous levez StopIteration ou automatiquement que le sous-itérateur est un générateur (en renvoyant une valeur par le sous-générateur).

Modifié dans la version 3.3: yield from <expr> a été ajoutée pour déléguer le contrôle du flot d’exécution à un sous-itérateur.

Les parenthèses peuvent être omises quand l’expression yield est la seule expression à droite de l’instruction de l’instruction d’assignation.

Voir aussi

PEP 255: Générateurs simples
La proposition d’ajouter à Python des générateurs et l’instruction yield.
PEP 342 - Coroutines via des générateurs améliorés
Proposition d’améliorer l’API et la syntaxe des générateurs, de manière à pouvoir les utiliser comme de simples coroutines.
PEP 380 - Syntaxe pour déléguer à un sous-générateur
Proposition d’introduire la syntaxe yield_from, de manière à déléguer facilement l’exécution à un sous-générateur.

6.2.9.1. Méthodes des générateurs-itérateurs

Cette sous-section décrit les méthodes des générateurs-itérateurs. Elles peuvent être utilisées pour contrôler l’exécution des fonctions générateurs.

Notez que l’appel à une méthode ci-dessous d’un générateur alors que le générateur est déjà en cours d’exécution lève une exception ValueError.

generator.__next__()

Démarre l’exécution d’une fonction générateur ou la reprend à la dernière expression yield exécutée. Quand une fonction générateur est reprise par une méthode __next__(), l’expression yield en cours s’évalue toujours à None. L’exécution continue ensuite jusqu’à l’expression yield suivante, où le générateur est à nouveau suspendu et la valeur de expression_list est renvoyée à la méthode __next__() de l’appelant. Si le générateur termine sans donner une autre valeur, une exception StopIteration est levée.

Cette méthode est normalement appelée implicitement, par exemple par une boucle for ou par la fonction native next().

generator.send(value)

Reprend l’exécution et « envoie » une valeur à la fonction générateur. L’argument value devient le résultat de l’expression yield courante. La méthode send() renvoie la valeur suivante produite par le générateur ou lève StopIteration si le générateur termine sans produire de nouvelle valeur. Quand send() est utilisée pour démarrer le générateur, elle doit avoir None comme argument, car il n’y a aucune expression yield qui peut recevoir la valeur.

generator.throw(type[, value[, traceback]])

Leve une exception de type type à l’endroit où le générateur est en pause et renvoie la valeur suivante produite par la fonction générateur. Si le générateur termine sans produire de nouvelle valeur, une exception StopIteration est levée. Si la fonction générateur ne gère pas l’exception passée ou lève une autre exception, alors cette exception est propagée vers l’appelant.

generator.close()

Lève une GeneratorExit à l’endroit où la fonction générateur a été mise en pause. Si la fonction générateur termine, est déjà fermée ou lève GeneratorExit (parce qu’elle ne gère pas l’exception), close revient vers l’appelant. Si le générateur produit une valeur, une RuntimeError est levée. Si le générateur lève une autre exception, elle est propagée à l’appelant. La méthode close() ne fait rien si le générateur a déjà terminé en raison d’une exception ou d’une fin normale.

6.2.9.2. Exemples

Voici un exemple simple qui montre le comportement des générateurs et des fonctions générateurs :

>>> def echo(value=None):
...     print("Execution starts when 'next()' is called for the first time.")
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception as e:
...                 value = e
...     finally:
...         print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

Pour des exemples d’utilisation de yield from, lisez la PEP 380: Syntax for Delegating to a Subgenerator dans « Les nouveautés de Python ».

6.2.9.3. Fonctions générateurs asynchrones

La présence d’une expression yield dans une fonction ou une méthode définie en utilisant async def transforme cette fonction en fonction générateur asynchrone.

Quand une fonction générateur asynchrone est appelée, elle renvoie un itérateur asynchrone, autrement appelé objet générateur asynchrone. Cet objet contrôle l’exécution de la fonction générateur. Un objet générateur asynchrone est typiquement utilisé dans une instruction async for à l’intérieur d’une fonction coroutine de la même manière qu’un objet générateur serait utilisé dans une instruction for.

L’appel d’une méthode du générateur asynchrone renvoie un objet awaitable et l’exécution commence au moment où l’on atteint une instruction await le concernant. À ce moment, l’exécution se déroule jusqu’à la première expression yield, où elle est suspendue et renvoie la valeur de expression_list à la coroutine en attente. Comme pour un générateur, la suspension signifie que tous les états locaux sont conservés, y compris les liaisons des variables locales, le pointeur d’instruction, la pile d’évaluation interne et l’état de tous les gestionnaires d’exceptions. Lorsque l’exécution reprend parce que l’appelant a atteint une instruction await sur l’objet suivant retourné par les méthodes du générateur asynchrone, la fonction s’exécute exactement comme si l’expression yield n’avait été qu’un simple appel externe. La valeur de l’expression yield au moment de la reprise dépend de la méthode qui a relancé l’exécution. Si c’est __anext__() qui a été utilisée, alors le résultat est None. Sinon, si c’est asend() qui a été utilisée, alors le résultat est la valeur transmise à cette méthode.

Dans une fonction générateur asynchrone, les expressions yield sont autorisées n’importe où dans une construction try. Cependant, si l’exécution d’un générateur asynchrone n’a pas repris avant que le générateur ne soit finalisé (parce que son compteur de référence a atteint zéro ou parce qu’il est nettoyé par le ramasse-miettes), alors une expression yield dans une construction try pourrait ne pas atteindre la clause finally en attente. Dans ce cas, c’est la responsabilité de la boucle d’événements ou du programmateur exécutant le générateur asynchrone d’appeler la méthode aclose() du générateur asynchrone et d’exécuter l’objet coroutine résultant, permettant ainsi à toute clause finally en attente d’être exécutée.

Pour effectuer correctement la finalisation, une boucle d’événements doit définir une fonction finalizer qui prend un générateur-itérateur asynchrone, appelle sans doute aclose() et exécute la coroutine. Ce finalizer peut s’enregistrer en appelant sys.set_asyncgen_hooks(). Lors de la première itération, un générateur-itérateur asynchrone stocke le finalizer enregistré à appeler lors de la finalisation. Pour un exemple de référence relatif à une méthode de finalizer, regardez l’implémentation de asyncio.Loop.shutdown_asyncgens dans Lib/asyncio/base_events.py.

L’expression yield from <expr> produit une erreur de syntaxe quand elle est utilisée dans une fonction générateur asynchrone.

6.2.9.4. Méthodes des générateurs-itérateurs asynchrones

Cette sous-section décrit les méthodes des générateurs-itérateurs asynchrones. Elles sont utilisées pour contrôler l’exécution des fonctions générateurs.

coroutine agen.__anext__()

Renvoie un awaitable qui, quand il a la main, démarre l’exécution du générateur asynchrone ou reprend son exécution à l’endroit de la dernière expression yield exécutée. Quand une fonction générateur asynchrone est reprise par une méthode __anext__(), l’expression yield en cours s’évalue toujours à None dans le awaitable renvoyé, et elle continue son exécution jusqu’à l’expression yield suivante. La valeur de expression_list de l’expression yield est la valeur de l’exception StopIteration levée par la coroutine qui termine. Si le générateur asynchrone termine sans produire d’autre valeur, le awaitable lève une exception StopAsyncIteration qui signale que l’itération asynchrone est terminée.

Cette méthode est normalement appelée implicitement par une boucle async for.

coroutine agen.asend(value)

Renvoie un awaitable qui, lorsqu’il a la main, reprend l’exécution du générateur asynchrone. Comme pour la méthode send() d’un générateur, elle « envoie » une valeur value à la fonction générateur asynchrone et cet argument devient le résultat de l’expression yield courante. Le awaitable renvoyé par la méthode asend() renvoie la valeur suivante produite par le générateur comme valeur de l’exception StopIteration levée ou lève StopAsyncIteration si le générateur asynchrone termine sans produire de nouvelle valeur. Quand asend() est appelée pour démarrer le générateur asynchrone, l’argument doit être None car il n’y a pas d’expression yield pour recevoir la valeur.

coroutine agen.athrow(type[, value[, traceback]])

Renvoie un awaitable qui lève une exception du type type à l’endroit où le générateur asynchrone a été mis en pause et renvoie la valeur suivante produite par la fonction générateur comme valeur de l’exception StopIteration qui a été levée. Si le générateur asynchrone termine sans produire de nouvelle valeur, une exception StopAsyncIteration est levée par le awaitable. Si la fonction générateur ne traite pas l’exception reçue ou lève une autre exception alors, quand le awaitable est lancé, cette exception est propagée vers l’appelant du awaitable.

coroutine agen.aclose()

Renvoie un awaitable qui, quand il s’exécute, lève une exception GeneratorExit dans la fonction générateur asynchrone à l’endroit où le générateur était en pause. Si la fonction générateur asynchrone termine normalement, est déjà fermée ou lève GeneratorExit (parce qu’elle ne gère pas l’exception), alors le awaitable renvoyé lève une exception StopIteration. Tout nouveau awaitable produit par un appel postérieur au générateur asynchrone lève une exception StopAsyncIteration. Si le générateur asynchrone produit une valeur, une RuntimeError est levée par le awaitable. Si le générateur asynchrone lève une autre exception, elle est propagée à l’appelant du awaitable. Si le générateur asynchrone a déjà terminé (soit par une exception, soit normalement), alors tout nouvel appel à aclose() renvoie un awaitable qui ne fait rien.

6.3. Primaires

Les primaires (primary dans la grammaire formelle ci-dessous) représentent les opérations qui se lient au plus proche dans le langage. Leur syntaxe est :

primary ::=  atom | attributeref | subscription | slicing | call

6.3.1. Références à des attributs

Une référence à un attribut (attributeref dans la grammaire formelle ci-dessous) est une primaire suivie par un point et un nom :

attributeref ::=  primary "." identifier

La primaire doit s’évaluer à un objet d’un type qui gère les références aux attributs, ce qui est le cas de la plupart des objets. Cet objet doit alors produire l’attribut dont le nom est « identifier ». Cette production peut être personnalisée en surchargeant la méthode __getattr__(). Si l’attribut n’est pas disponible, une exception AttributeError est levée. Sinon, le type et la valeur de l’objet produit sont déterminés par l’objet. Plusieurs évaluations successives d’une référence à un même attribut peuvent produire différents objets.

6.3.2. Sélections

Une sélection (subscription dans la grammaire formelle ci-dessous) désigne un élément dans un objet séquence (chaîne, n-uplet ou liste) ou tableau de correspondances (dictionnaire) :

subscription ::=  primary "[" expression_list "]"

La primaire doit s’appliquer à un objet qui gère les sélections (une liste ou un dictionnaire par exemple). Les objets définis par l’utilisateur peuvent gérer les sélections en définissant une méthode __getitem__().

Pour les objets natifs, deux types d’objets gèrent la sélection :

Si la primaire est un tableau de correspondances, la liste d’expressions (expression_list dans la grammaire formelle ci-dessous) doit pouvoir être évaluée comme un objet dont la valeur est une des clés du tableau de correspondances et la sélection désigne la valeur qui correspond à cette clé (la liste d’expressions est un n-uplet sauf si elle comporte exactement un élément).

Si la primaire est une séquence, la liste d’expressions (expression_list dans la grammaire) doit pouvoir être évaluée comme un entier ou une tranche (comme expliqué dans la section suivante).

La syntaxe formelle ne traite pas des cas d’indices négatifs dans les séquences ; cependant, toutes les séquences natives possèdent une méthode __getitem__() qui interprète les indices négatifs en ajoutant la longueur de la séquence à l’indice (de manière à ce que x[-1] sélectionne le dernier élément de x). La valeur résultante doit être un entier positif ou nul, inférieur au nombre d’éléments dans la séquence ; la sélection désigne alors l’élément dont l’indice est cette valeur (en comptant à partir de zéro). Comme la gestion des indices négatifs et des tranches est faite par la méthode __getitem__(), les sous-classes qui surchargent cette méthode doivent aussi savoir les gérer, de manière explicite.

Les éléments des chaînes sont des caractères. Un caractère n’est pas un type en tant que tel, c’est une chaîne de longueur un.

6.3.3. Tranches

Une tranche (slicing dans la grammaire formelle ci-dessous) sélectionne un intervalle d’éléments d’un objet séquence (par exemple une chaîne, un n-uplet ou une liste, respectivement les types string, tuple et list). Les tranches peuvent être utilisées comme des expressions ou des cibles dans les assignations ou les instructions del. La syntaxe est la suivante :

slicing      ::=  primary "[" slice_list "]"
slice_list   ::=  slice_item ("," slice_item)* [","]
slice_item   ::=  expression | proper_slice
proper_slice ::=  [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound  ::=  expression
upper_bound  ::=  expression
stride       ::=  expression

Il existe une ambigüité dans la syntaxe formelle ci-dessus : tout ce qui ressemble à une liste d’expressions (expression_list vue avant) ressemble aussi à une liste de tranches (slice_list dans la grammaire ci-dessus). En conséquence, toute sélection (subscription dans la grammaire) peut être interprétée comme une tranche. Plutôt que de compliquer encore la syntaxe, l’ambigüité est levée en disant que, dans ce cas, l’interprétation en tant que sélection (subscription) est prioritaire sur l’interprétation en tant que tranche (c’est le cas si la liste de tranches (slice_list) ne contient aucune tranche en tant que telle).

La sémantique pour une tranche est définie comme suit. La primaire est indicée (en utilisant la même méthode __getitem__() que pour les sélections normales) avec une clé qui est construite à partir de la liste de tranches (slice_list dans la grammaire), de cette manière : si la liste de tranches contient au moins une virgule (,), la clé est un n-uplet contenant la conversion des éléments de la tranche ; sinon, la conversion du seul élément de la tranche est la clé. La conversion d’un élément de tranche qui est une expression est cette expression. La conversion d’une tranche en tant que telle est un objet slice (voir la section Hiérarchie des types standards) dont les attributs start, stop et step sont les valeurs des expressions données pour la borne inférieure (lower_bound dans la grammaire), la borne supérieure (upper_bound dans la grammaire) et le pas (stride dans la grammaire), respectivement. En cas d’expression manquante, la valeur par défaut est None.

6.3.4. Appels

Un appel (call dans la grammaire ci-dessous) appelle un objet appelable (par exemple, une fonction) avec, possiblement, une liste d”arguments :

call                 ::=  primary "(" [argument_list [","] | comprehension] ")"
argument_list        ::=  positional_arguments ["," starred_and_keywords]
                            ["," keywords_arguments]
                          | starred_and_keywords ["," keywords_arguments]
                          | keywords_arguments
positional_arguments ::=  ["*"] expression ("," ["*"] expression)*
starred_and_keywords ::=  ("*" expression | keyword_item)
                          ("," "*" expression | "," keyword_item)*
keywords_arguments   ::=  (keyword_item | "**" expression)
                          ("," keyword_item | "," "**" expression)*
keyword_item         ::=  identifier "=" expression

Une virgule finale (optionnelle) peut être présente, après les arguments positionnels et par mots-clés, mais elle n’affecte pas la sémantique.

La primaire doit s’évaluer à un objet appelable (une fonction définie par l’utilisateur, une fonction native, une méthode d’objet natif, un objet de classe, une méthode d’instance de classe ou tout objet possédant une méthode __call__() est un appelable). Toutes les expressions des arguments sont évaluées avant que l’appel ne soit exécuté. Référez-vous à la section Définition de fonctions pour la syntaxe des listes de paramètres formels.

Si des arguments par mots-clés sont présents, ils sont d’abord convertis en arguments positionnels, comme suit. Pour commencer, une liste de slots vides est créée pour les paramètres formels. S’il y a N arguments positionnels, ils sont placés dans les N premiers slots. Ensuite, pour chaque argument par mot-clé, l’identifiant est utilisé pour déterminer le slot correspondant (si l’identifiant est le même que le nom du premier paramètre formel, le premier slot est utilisé, et ainsi de suite). Si le slot est déjà rempli, une exception TypeError est levée. Sinon, la valeur de l’argument est placée dans le slot, ce qui le remplit (même si l’expression est None, cela remplit le slot). Quand tous les arguments ont été traités, les slots qui sont toujours vides sont remplis avec la valeur par défaut correspondante dans la définition de la fonction (les valeurs par défaut sont calculées, une seule fois, lorsque la fonction est définie ; ainsi, un objet mutable tel qu’une liste ou un dictionnaire utilisé en tant valeur par défaut sera partagé entre tous les appels qui ne spécifient pas de valeur d argument pour ce slot ; on évite généralement de faire ça). S’il reste des slots pour lesquels aucune valeur par défaut n’est définie, une exception TypeError est levée. Sinon, la liste des slots remplie est utilisée en tant que liste des arguments pour l’appel.

Particularité de l’implémentation CPython : Une implémentation peut fournir des fonctions natives dont les paramètres positionnels n’ont pas de nom, même s’ils sont « nommés » pour les besoins de la documentation. Ils ne peuvent donc pas être spécifiés par mot-clé. En CPython, les fonctions implémentées en C qui utilisent PyArg_ParseTuple() pour analyser leurs arguments en font partie.

S’il y a plus d’arguments positionnels que de slots de paramètres formels, une exception TypeError est levée, à moins qu’un paramètre formel n’utilise la syntaxe *identifier ; dans ce cas, le paramètre formel reçoit un n-uplet contenant les arguments positionnels en supplément (ou un n-uplet vide s’il n’y avait pas d’arguments positionnel en trop).

Si un argument par mot-clé ne correspond à aucun nom de paramètre formel, une exception TypeError est levée, à moins qu’un paramètre formel n’utilise la syntaxe **identifier ; dans ce cas, le paramètre formel reçoit un dictionnaire contenant les arguments par mot-clé en trop (en utilisant les mots-clés comme clés et les arguments comme valeurs pour ce dictionnaire), ou un (nouveau) dictionnaire vide s’il n’y a pas d’argument par mot-clé en trop.

Si la syntaxe *expression apparaît dans l’appel de la fonction, expression doit pouvoir s’évaluer à un itérable. Les éléments de ces itérables sont traités comme s’ils étaient des arguments positionnels supplémentaires. Pour l’appel f(x1, x2, *y, x3, x4), si y s’évalue comme une séquence y1, …, yM, c’est équivalent à un appel avec M+4 arguments positionnels x1, x2, y1, …, yM, x3, x4.

Une conséquence est que bien que la syntaxe *expression puisse apparaître après les arguments par mots-clés explicites, ils sont traités avant les arguments par mots-clés (et avant tout argument **expression – voir ci-dessous). Ainsi :

>>> def f(a, b):
...     print(a, b)
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2

Il est inhabituel que les syntaxes d’arguments par mots-clés et *expression soient utilisés simultanément dans un même appel, ce qui fait que la confusion reste hypothétique.

Si la syntaxe **expression apparaît dans un appel de fonction, expression doit pouvoir s’évaluer comme un tableau de correspondances, dont le contenu est traité comme des arguments par mots-clés supplémentaires. Si un mot-clé est déjà présent (en tant qu’argument par mot-clé explicite, ou venant d’un autre dépaquetage), une exception TypeError est levée.

Les paramètres formels qui utilisent la syntaxe *identifier ou **identifier ne peuvent pas être utilisés comme arguments positionnels ou comme noms d’arguments par mots-clés.

Modifié dans la version 3.5: Les appels de fonction acceptent n’importe quel nombre de dépaquetages par * ou **. Des arguments positionnels peuvent suivre les dépaquetages d’itérables (*) et les arguments par mots-clés peuvent suivre les dépaquetages de dictionnaires (**). Proposé pour la première fois par la PEP 448.

Un appel renvoie toujours une valeur, possiblement None, à moins qu’il ne lève une exception. La façon dont celle valeur est calculée dépend du type de l’objet appelable.

Si c’est —

une fonction définie par l’utilisateur :

le bloc de code de la fonction est exécuté, il reçoit la liste des arguments. La première chose que le bloc de code fait est de lier les paramètres formels aux arguments ; ceci est décrit dans la section Définition de fonctions. Quand le bloc de code exécute l’instruction return, cela spécifie la valeur de retour de l’appel de la fonction.

une fonction ou une méthode native :

le résultat dépend de l’interpréteur ; lisez Fonctions natives pour une description des fonctions et méthodes natives.

un objet classe :

une nouvelle instance de cette classe est renvoyée.

une méthode d’instance de classe :

la fonction correspondante définie par l’utilisateur est appelée, avec la liste d’arguments qui est plus grande d’un élément que la liste des arguments de l’appel : l’instance est placée en tête des arguments.

une instance de classe :

la classe doit définir une méthode __call__() ; l’effet est le même que si cette méthode était appelée.

6.4. Expression await

Suspend l’exécution de la coroutine sur un objet awaitable. Ne peut être utilisée qu’à l’intérieur d’une coroutine function.

await_expr ::=  "await" primary

Nouveau dans la version 3.5.

6.5. L’opérateur puissance

L’opérateur puissance est plus prioritaire que les opérateurs unaires sur sa gauche ; il est moins prioritaire que les opérateurs unaires sur sa droite. La syntaxe est :

power ::=  (await_expr | primary) ["**" u_expr]

Ainsi, dans une séquence sans parenthèse de puissance et d’opérateurs unaires, les opérateurs sont évalués de droite à gauche (ceci ne contraint pas l’ordre d’évaluation des opérandes) : -1**2 donne -1.

L’opérateur puissance possède la même sémantique que la fonction native pow() lorsqu’elle est appelée avec deux arguments : il produit son argument de gauche élevé à la puissance de son argument de droite. Les arguments numériques sont d’abord convertis vers un type commun et le résultat est de ce type.

Pour les opérandes entiers, le résultat est du même type à moins que le deuxième argument ne soit négatif ; dans ce cas, tous les arguments sont convertis en nombres à virgule flottante et le résultat est un nombre à virgule flottante. Par exemple, 10**2 renvoie 100 mais 10**-2 renvoie 0.01.

Élever 0.0 à une puissance négative entraîne une ZeroDivisionError. Élever un nombre négatif à une puissance fractionnaire renvoie un nombre complexe (dans les versions antérieures, cela levait une ValueError).

6.6. Arithmétique unaire et opérations sur les bits

Toute l’arithmétique unaire et les opérations sur les bits ont la même priorité :

u_expr ::=  power | "-" u_expr | "+" u_expr | "~" u_expr

L’opérateur unaire - (moins) produit l’opposé de son argument numérique.

L’opérateur unaire + (plus) produit son argument numérique inchangé.

L’opérateur unaire ~ (inversion) produit l’inversion bit à bit de son argument entier. L’inversion bit à bit de x est définie comme -(x+1). Elle s’applique uniquement aux nombres entiers.

Dans ces trois cas, si l’argument n’est pas du bon type, une exception TypeError est levée.

6.7. Opérations arithmétiques binaires

Les opérations arithmétiques binaires suivent les conventions pour les priorités. Notez que certaines de ces opérations s’appliquent aussi à des types non numériques. À part l’opérateur puissance, il n’y a que deux niveaux, le premier pour les opérateurs multiplicatifs et le second pour les opérateurs additifs :

m_expr ::=  u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
            m_expr "//" u_expr | m_expr "/" u_expr |
            m_expr "%" u_expr
a_expr ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr

L’opérateur * (multiplication) produit le produit de ses arguments. Les deux arguments doivent être des nombres ou alors le premier argument doit être un entier et l’autre doit être une séquence. Dans le premier cas, les nombres sont convertis dans un type commun puis sont multipliés entre eux. Dans le dernier cas, la séquence est répétée ; une répétition négative produit une séquence vide.

L’opérateur @ (at) a vocation à multiplier des matrices. Aucun type Python natif n’implémente cet opérateur.

Nouveau dans la version 3.5.

Les opérateurs / (division) and // (division entière ou floor division en anglais) produisent le quotient de leurs arguments. Les arguments numériques sont d’abord convertis vers un type commun. La division d’entiers produit un nombre à virgule flottante alors que la division entière d’entiers produit un entier ; le résultat est celui de la division mathématique suivie de la fonction “floor” appliquée au résultat. Une division par zéro lève une exception ZeroDivisionError.

L’opérateur % (modulo) produit le reste de la division entière du premier argument par le second. Les arguments numériques sont d’abord convertis vers un type commun. Un zéro en second argument lève une exception ZeroDivisionError. Les arguments peuvent être des nombres à virgule flottante, par exemple 3.14%0.7 vaut 0.34 (puisque 3.14 égale 4*0.7+0.34). L’opérateur modulo produit toujours un résultat du même signe que le second opérande (ou zéro) ; la valeur absolue du résultat est strictement inférieure à la valeur absolue du second opérande [1].

Les opérateurs division entière et modulo sont liés par la relation suivante : x == (x//y)*y + (x%y). La division entière et le module sont aussi liés à la fonction native divmod() : divmod(x, y) == (x//y, x%y) [2].

En plus de calculer le modulo sur les nombres, l’opérateur % est aussi surchargé par les objets chaînes de caractères pour effectuer le formatage de chaîne « à l’ancienne ». La syntaxe pour le formatage de chaînes est décrit dans la référence de la bibliothèque Python, dans la section Formatage de chaines à la printf.

L’opérateur de division entière, l’opérateur modulo et la fonction divmod() ne sont pas définis pour les nombres complexes. À la place, vous pouvez, si cela a du sens pour ce que vous voulez faire, les convertir vers des nombres à virgule flottante en utilisant la fonction abs().

L’opérateur + (addition) produit la somme de ses arguments. Les arguments doivent être tous les deux des nombres ou des séquences du même type. Dans le premier cas, les nombres sont convertis vers un type commun puis sont additionnés entre eux. Dans le dernier cas, les séquences sont concaténées.

L’opérateur - (soustraction) produit la différence entre ses arguments. Les arguments numériques sont d’abord convertis vers un type commun.

6.8. Opérations de décalage

Les opérations de décalage sont moins prioritaires que les opérations arithmétiques :

shift_expr ::=  a_expr | shift_expr ("<<" | ">>") a_expr

Ces opérateurs prennent des entiers comme arguments. Ils décalent le premier argument vers la gauche ou vers la droite du nombre de bits donné par le deuxième argument.

Un décalage à droite de n bits est défini comme la division entière par pow(2,n). Un décalage à gauche de n bits est défini comme la multiplication par pow(2,n).

6.9. Opérations binaires bit à bit

Chacune des trois opérations binaires bit à bit possède une priorité différente :

and_expr ::=  shift_expr | and_expr "&" shift_expr
xor_expr ::=  and_expr | xor_expr "^" and_expr
or_expr  ::=  xor_expr | or_expr "|" xor_expr

L’opérateur & produit le ET logique de ses arguments, qui doivent être des entiers.

L’opérateur ^ produit le OU EXCLUSIF (XOR) logique de ses arguments, qui doivent être des entiers.

L’opérateur | produit le OU logique de ses arguments, qui doivent être des entiers.

6.10. Comparaisons

Au contraire du C, toutes les opérations de comparaison en Python possèdent la même priorité, qui est plus faible que celle des opérations arithmétiques, décalages ou binaires bit à bit. Toujours contrairement au C, les expressions telles que a < b < c sont interprétées comme elles le seraient conventionnellement en mathématiques :

comparison    ::=  or_expr (comp_operator or_expr)*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

Les comparaisons produisent des valeurs booléennes : True ou False.

Les comparaisons peuvent être enchaînées arbitrairement, par exemple x < y <= z est équivalent à x < y and y <= z, sauf que y est évalué seulement une fois (mais dans les deux cas, z n’est pas évalué du tout si x < y s’avère être faux).

Formellement, si a, b, c, …, y, z sont des expressions et op1, op2, …, opN sont des opérateurs de comparaison, alors a op1 b op2 c ... y opN z est équivalent à a op1 b and b op2 c and ... y opN z, sauf que chaque expression est évaluée au maximum une fois.

Notez que a op1 b op2 c n’implique aucune comparaison entre a et c. Ainsi, par exemple, x < y > z est parfaitement légal (mais peut-être pas très élégant).

6.10.1. Comparaisons de valeurs

Les opérateurs <, >, ==, >=, <= et != comparent les valeurs de deux objets. Les objets n’ont pas besoin d’être du même type.

Le chapître Objets, valeurs et types indique que les objets ont une valeur (en plus d’un type et d’un identifiant). La valeur d’un objet est une notion plutôt abstraite en Python : par exemple, il n’existe pas de méthode canonique pour accéder à la valeur d’un objet. De la même manière, il n’y a aucune obligation concernant la construction de la valeur d’un objet, par exemple qu’elle prenne en compte toutes les données de ses attributs. Les opérateurs de comparaison implémentent une notion particulière de ce qu’est la valeur d’un objet. Vous pouvez vous le représenter comme une définition indirecte de la valeur d’un objet, via l’implémentation de leur comparaison.

Comme tous les types sont des sous-types (directs ou indirects) de la classe object, ils héritent du comportement de comparaison par défaut de object. Les types peuvent personnaliser le comportement des comparaisons en implémentant des méthodes de comparaisons riches, comme __lt__(), décrites dans Personnalisation de base.

Le comportement par défaut pour le test d’égalité (== et !=) se base sur les identifiants des objets. Ainsi, un test d’égalité entre deux instances qui ont le même identifiant est vrai, un test d’égalité entre deux instances qui ont des identifiants différents est faux. La raison de ce choix est que Python souhaite que tous les objets soient réflexifs, c’est-à-dire que x is y implique x == y.

La relation d’ordre (<, >, <= et >=) n’est pas fournie par défaut ; une tentative se solde par une TypeError. La raison de ce choix est qu’il n’existe pas d’invariant similaire à celui de l’égalité.

Le comportement du test d’égalité par défaut, à savoir que les instances avec des identités différentes ne sont jamais égales, peut être en contradiction avec les types qui définissent la « valeur » d’un objet et se basent sur cette « valeur » pour l’égalité. De tels types doivent personnaliser leurs tests de comparaison et, en fait, c’est ce qu’ont fait un certain nombre de types natifs.

La liste suivante décrit le comportement des tests d’égalité pour les types natifs les plus importants.

  • Beaucoup de types numériques natifs (Types numériques — int, float, complex) et de types de la bibliothèque standard fractions.Fraction ainsi que decimal.decimal peuvent être comparés, au sein de leur propre classe ou avec d’autres objets de classes différentes. Une exception notable concerne les nombres complexes qui ne gèrent pas la relation d’ordre. Dans les limites des types concernés, la comparaison mathématique équivaut à la comparaison algorithmique, sans perte de précision.

    Les valeurs qui ne sont pas des nombres, float('NaN') et Decimal('NaN'), ont un traitement spécial.

  • Les séquences binaires (instances du type bytes ou bytearray) peuvent être comparées au sein de la classe et entre classes. La comparaison est lexicographique, en utilisant la valeur numérique des éléments.

  • Les chaînes de caractères (instances de str) respectent l’ordre lexicographique en utilisant la valeur Unicode (le résultat de la fonction native ord()) des caractères [3].

    Les chaînes de caractères et les séquences binaires ne peuvent pas être comparées directement.

  • Les séquences (instances de tuple, list ou range) peuvent être comparées uniquement entre instances de même type, en sachant que les intervalles (range) ne gèrent pas la relation d’ordre. Le test d’égalité entre ces types renvoie faux et une comparaison entre instances de types différents lève une TypeError.

    Les séquences suivent l’ordre lexicographique en utilisant la comparaison de leurs éléments, sachant que la réflexivité des éléments est appliquée.

    Dans l’application de la réflexivité des éléments, la comparaison des collections suppose que pour un élément de collection x, x == x est toujours vrai. Sur la base de cette hypothèse, l’identité des éléments est d’abord testée, puis la comparaison des éléments n’est effectuée que pour des éléments distincts. Cette approche donne le même résultat qu’une comparaison stricte d’éléments, si les éléments comparés sont réflexifs. Pour les éléments non réflexifs, le résultat est différent de celui de la comparaison stricte des éléments, voire peut être surprenant : les valeurs non réflexives qui ne sont pas des nombres, par exemple, aboutissent au comportement suivant lorsqu’elles sont utilisées dans une liste :

    >>> nan = float('NaN')
    >>> nan is nan
    True
    >>> nan == nan
    False                 <-- the defined non-reflexive behavior of NaN
    >>> [nan] == [nan]
    True                  <-- list enforces reflexivity and tests identity first
    

    L’ordre lexicographique pour les collections natives fonctionne comme suit :

    • Deux collections sont égales si elles sont du même type, ont la même longueur et si les éléments correspondants de chaque paire sont égaux. Par exemple, [1,2] == (1,2) est faux car les types sont différents.
    • Les collections qui gèrent la relation d’ordre sont ordonnées comme leur premier élément différent (par exemple, [1,2,x] <= [1,2,y] a la même valeur que x <= y). Si un élément n’a pas de correspondant, la collection la plus courte est la plus petite (par exemple, [1,2] < [1,2,3] est vrai).
  • Les tableaux de correspondances (instances de dict) sont égales si et seulement si toutes leurs paires (clé, valeur) sont égales. L’égalité des clés et des valeurs met en œuvre la réflexivité.

    Les comparaisons (<, >, <= et >=) lèvent TypeError.

  • Les ensembles (instances de set ou frozenset) peuvent être comparés au sein de leur propre type et entre types différents.

    Les opérateurs d’inclusion et de sur-ensemble sont définis. Ces relations ne sont pas des relations d’ordre total (par exemple, les deux ensembles {1,2} et {2,3} ne sont pas égaux, l’un n’est pas inclus dans l’autre, l’un n’est pas un sur-ensemble de l’autre). Ainsi, les ensembles ne sont pas des arguments appropriés pour les fonctions qui dépendent d’un ordre total (par exemple, les fonctions min(), max() et sorted() produisent des résultats indéfinis si on leur donne des listes d’ensembles en entrée).

    La comparaison des ensembles met en œuvre la réflexivité des éléments.

  • La plupart des autres types natifs n’implémentent pas de méthodes de comparaisons, ils héritent donc du comportement par défaut.

Les classes allogènes qui particularisent les opérations de comparaison doivent, si possible, respecter quelques règles pour la cohérence :

  • Le test d’égalité doit être réflexif. En d’autres termes, des objets identiques doivent être égaux :

    x is y implique x == y

  • La comparaison doit être symétrique. En d’autres termes, les expressions suivantes doivent donner le même résultat :

    x == y et y == x

    x != y et y != x

    x < y et y > x

    x <= y et y >= x

  • La comparaison doit être transitive. Les exemples suivants (liste non exhaustive) illustrent ce concept :

    x > y and y > z implique x > z

    x < y and y <= z implique x < z

  • Si vous inversez la comparaison, le résultat a négation

    x == y et not x != y

    x < y et not x >= y (pour une relation d’ordre total)

    x > y et not x <= y (pour une relation d’ordre total)

    Ces deux dernières expressions s’appliquent pour les collections totalement ordonnées (par exemple, les séquences mais pas les ensembles ou les tableaux de correspondances). Regardez aussi le décorateur total_ordering().

  • Le résultat de hash() doit être cohérent avec l’égalité. Les objets qui sont égaux doivent avoir la même empreinte ou être marqués comme non-hachables.

Python ne vérifie pas ces règles de cohérence. En fait, l’utilisation de valeurs non numériques est un exemple de non-respect de ces règles.

6.10.2. Opérations de tests d’appartenance à un ensemble

Les opérateurs in et not in testent l’appartenance. x in s s’évalue à True si x appartient à s et à False sinon. x not in s renvoie la négation de x in s. Tous les types séquences et ensembles natifs gèrent ces opérateurs, ainsi que les dictionnaires pour lesquels in teste si dictionnaire possède une clé donnée. Pour les types conteneurs tels que les listes, n-uplets (tuple), ensembles (set), ensembles gelés (frozen set), dictionnaires (dict) ou collections.deque, l’expression x in y est équivalente à any(x is e or x == e for e in y).

Pour les chaînes de caractères et chaînes d’octets, x in y vaut True si et seulement si x est une sous-chaîne de y. Un test équivalent est y.find(x) != -1. Une chaîne vide est considérée comme une sous-chaîne de toute autre chaîne, ainsi "" in "abc" renvoie True.

Pour les classes allogènes qui définissent la méthode __contains__(), x in y renvoie True si y.__contains__(x) renvoie vrai, et False sinon.

Pour les classes allogènes qui ne définissent pas __contains__() mais qui définissent __iter__(), x in y vaut True s’il existe une valeur z telle que x == z renvoie vrai lors de l’itération sur y. Si une exception est levée pendant l’itération, c’est comme si in avait levé cette exception.

Enfin, le protocole d’itération « à l’ancienne » est essayé : si la classe définit __getitem__(), x in y est True si et seulement si il existe un entier positif ou nul i, représentant l’indice, tel que x == y[i] et que tout indice inférieur ne lève pas d’exception IndexError (si toute autre exception est levée, c’est comme si in avait levé cette exception).

L’opérateur not in est défini comme produisant le contraire de in.

6.10.3. Comparaisons d’identifiants

Les opérateurs is et is not testent l’égalité des identifiants des objets : x is y est vrai si et seulement si x et y sont le même objet. L’identifiant d’un objet est déterminé en utilisant la fonction id(). x is not y renvoie le résultat contraire de l’égalité des identifiants [4].

6.11. Opérations booléennes

or_test  ::=  and_test | or_test "or" and_test
and_test ::=  not_test | and_test "and" not_test
not_test ::=  comparison | "not" not_test

Dans le contexte des opérations booléennes et quand des expressions sont utilisées par des instructions de contrôle du flux d’exécution, les valeurs suivantes sont considérées comme fausses : False, None, zéro quel que soit le type, la chaîne vide et tout conteneur vide (y compris les chaînes, n-uplets, listes, dictionnaires, ensembles, ensembles gelés). Toutes les autres valeurs sont considérées comme vraies. Les objets allogènes peuvent personnaliser leur table de vérité en implémentant une méthode __bool__().

L’opérateur not produit True si son argument est faux, False sinon.

L’expression x and y commence par évaluer x ; si x est faux, sa valeur est renvoyée ; sinon, y est évalué et la valeur résultante est renvoyée.

L’expression x or y commence par évaluer x ; si x est vrai, sa valeur est renvoyée ; sinon, y est évalué et la valeur résultante est renvoyée.

Notez que ni and ni or ne restreignent la valeur et le type qu’ils renvoient à False et True : ils renvoient le dernier argument évalué. Ceci peut être utile, par exemple : si une chaîne s doit être remplacée par une valeur par défaut si elle est vide, l’expression s or 'truc' produit la valeur voulue. Comme not doit créer une nouvelle valeur, il renvoie une valeur booléenne quel que soit le type de son argument (par exemple, not 'truc' produit False plutôt que ''.

6.12. Expressions conditionnelles

conditional_expression ::=  or_test ["if" or_test "else" expression]
expression             ::=  conditional_expression | lambda_expr
expression_nocond      ::=  or_test | lambda_expr_nocond

Les expressions conditionnelles (parfois appelées « opérateur ternaire ») sont les moins prioritaires de toutes les opérations Python.

L’expression x if C else y commence par évaluer la condition C. Si C est vrai, alors x est évalué et sa valeur est renvoyée ; sinon, y est évalué et sa valeur est renvoyée.

Voir la PEP 308 pour plus de détails sur les expressions conditionnelles.

6.13. Expressions lambda

lambda_expr        ::=  "lambda" [parameter_list]: expression
lambda_expr_nocond ::=  "lambda" [parameter_list]: expression_nocond

Les expressions lambda sont utilisées pour créer des fonctions anonymes. L’expression lambda parameters: expression produit un objet fonction. Cet objet anonyme se comporte comme un objet fonction défini par :

def <lambda>(parameters):
    return expression

Voir la section Définition de fonctions pour la syntaxe des listes de paramètres. Notez que les fonctions créées par des expressions lambda ne peuvent pas contenir d’instructions ou d’annotations.

6.14. Listes d’expressions

expression_list    ::=  expression ("," expression)* [","]
starred_list       ::=  starred_item ("," starred_item)* [","]
starred_expression ::=  expression | (starred_item ",")* [starred_item]
starred_item       ::=  expression | "*" or_expr

Sauf lorsqu’elle fait partie d’un agencement de liste ou d’ensemble, une liste d’expressions qui contient au moins une virgule produit un n-uplet (tuple). La longueur du n-uplet est le nombre d’expressions dans la liste. Les expressions sont évaluées de la gauche vers la droite.

Un astérisque * indique dépaquetage d’itérable (iterable unpacking en anglais). Son opérande doit être un iterable. L’itérable est développé en une séquence d’éléments qui sont inclus dans un nouvel objet tuple, list ou set à l’emplacement du dépaquetage.

Nouveau dans la version 3.5: dépaquetage d’itérables dans les listes d’expressions, proposé à l’origine par la PEP 448.

La virgule finale est nécessaire pour créer un singleton (c’est-à-dire un n-uplet composé d’un seul élément) : elle est optionnelle dans tous les autres cas. Une expression seule sans virgule finale ne crée pas un n-uplet mais produit la valeur de cette expression (pour créer un tuple vide, utilisez une paire de parenthèses vide : ()).

6.15. Ordre d’évaluation

Python évalue les expressions de la gauche vers la droite. Remarquez que lors de l’évaluation d’une assignation, la partie droite de l’assignation est évaluée avant la partie gauche.

Dans les lignes qui suivent, les expressions sont évaluées suivant l’ordre arithmétique de leurs suffixes :

expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2

6.16. Priorités des opérateurs

Le tableau suivant résume les priorités des opérateurs en Python, du moins prioritaire au plus prioritaire. Les opérateurs qui sont dans la même case ont la même priorité. À moins que la syntaxe ne soit explicitement indiquée, les opérateurs sont binaires. Les opérateurs dans la même cases regroupent de la gauche vers la droite (sauf pour la puissance qui regroupe de la droite vers la gauche).

Notez que les comparaisons, les tests d’appartenance et les tests d’identifiants possèdent tous la même priorité et s’enchaînent de la gauche vers la droite comme décrit dans la section Comparaisons.

Opérateur Description
lambda Expression lambda
ifelse Expressions conditionnelle
or OR (booléen)
and AND (booléen)
not x NOT (booléen)
in, not in, is, is not, <, <=, >, >=, !=, == Comparaisons, y compris les tests d’appartenance et les tests d’identifiants
| OR (bit à bit)
^ XOR (bit à bit)
& AND (bit à bit)
<<, >> décalages
+, - Addition et soustraction
*, @, /, //, % Multiplication, multiplication de matrices, division, division entière, reste [5]
+x, -x, ~x NOT (positif, négatif, bit à bit)
** Puissance [6]
await x Expression await
x[indice], x[indice:indice], x(arguments...), x.attribut indiçage, tranches, appel, référence à un attribut
(expressions...), [expressions...], {clé: valeur...}, {expressions...} liaison ou agencement de n-uplet, agencement de liste, agencement de dictionnaire, agencement d’ensemble

Notes

[1]Bien que abs(x%y) < abs(y) soit vrai mathématiquement, ce n’est pas toujours vrai pour les nombres à virgule flottante en raison des arrondis. Par exemple, en supposant que Python tourne sur une plateforme où les float sont des nombres à double précision IEEE 754, afin que -1e-100 % 1e100 soit du même signe que 1e100, le résultat calculé est -1e-100 + 1e100, qui vaut exactement 1e100 dans ce standard. Or, la fonction math.fmod() renvoie un résultat dont le signe est le signe du premier argument, c’est-à-dire -1e-100 dans ce cas. La meilleure approche dépend de l’application.
[2]Si x est très proche d’un multiple entier de y, il est possible que x/y soit supérieur de un par rapport à (x-x%y)//y en raison des arrondis. Dans de tels cas, Python renvoie le second résultat afin d’avoir divmod(x,y)[0] * y + x % y le plus proche de x.
[3]

Le standard Unicode distingue les points codes (code points en anglais, par exemple U+0041) et les caractères abstraits (abstract characters en anglais, par exemple « LATIN CAPITAL LETTER A »). Bien que la plupart des caractères abstraits de l’Unicode ne sont représentés que par un seul point code, il y a un certain nombre de caractères abstraits qui peuvent être représentés par une séquence de plus qu’un point code. Par exemple, le caractère abstrait « LATIN CAPITAL LETTER C WITH CEDILLA » peut être représenté comme un unique caractère précomposé au point code U+00C7, ou en tant que séquence d’un caractère de base à la position U+0043 (LATIN CAPITAL LETTER C) du code, suivi par un caractère combiné à la position U+0327 (COMBINING CEDILLA) du code.

Les opérateurs de comparaison des chaînes opèrent au niveau des points codes Unicode. Cela peut être déroutant pour des humains. Par exemple, "\u00C7" == "\u0043\u0327" renvoie False, bien que les deux chaînes représentent le même caractère abstrait « LATIN CAPITAL LETTER C WITH CEDILLA ».

Pour comparer des chaînes au niveau des caractères abstraits (afin d’avoir quelque chose d’intuitif pour les humains), utilisez unicodedata.normalize().

[4]En raison du ramasse-miettes automatique et de la nature dynamique des descripteurs, vous pouvez être confronté à un comportement semblant bizarre lors de certaines utilisations de l’opérateur is, par exemple si cela implique des comparaisons entre des méthodes d’instances ou des constantes. Allez vérifier dans la documentation pour plus d’informations.
[5]L’opérateur % est aussi utilisé pour formater les chaînes de caractères ; il y possède la même priorité.
[6]L’opérateur puissance ** est moins prioritaire qu’un opérateur unaire arithmétique ou bit à bit sur sa droite. Ainsi, 2**-1 vaut 0.5.