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.

6.2.1.1. Private name mangling

When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class.

Voir aussi

The class specifications.

More precisely, private names are transformed to a longer form before code is generated for them. If the transformed name is longer than 255 characters, implementation-defined truncation may happen.

The transformation is independent of the syntactical context in which the identifier is used but only the following private identifiers are mangled:

  • Any name used as the name of a variable that is assigned or read or any name of an attribute being accessed.

    The __name__ attribute of nested functions, classes, and type aliases is however not mangled.

  • The name of imported modules, e.g., __spam in import __spam. If the module is part of a package (i.e., its name contains a dot), the name is not mangled, e.g., the __foo in import __foo.bar is not mangled.

  • The name of an imported member, e.g., __f in from spam import __f.

The transformation rule is defined as follows:

  • The class name, with leading underscores removed and a single leading underscore inserted, is inserted in front of the identifier, e.g., the identifier __spam occurring in a class named Foo, _Foo or __Foo is transformed to _Foo__spam.

  • If the class name consists only of underscores, the transformation is the identity, e.g., the identifier __spam occurring in a class named _ or __ is left as is.

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 n-uplet) ; 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 n-uplet vide. Comme les n-uplets sont immuables, la même règle que pour les littéraux s'applique (c'est-à-dire que deux occurrences du n-uplet vide peuvent, ou pas, produire le même objet).

Notez que les n-uplets ne sont pas créés par les parenthèses mais par l'utilisation de la virgule. L'exception est le n-uplet 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 ::=  assignment_expression comp_for
comp_for      ::=  ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter     ::=  comp_for | comp_if
comp_if       ::=  "if" or_test [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.

Since Python 3.6, in an async def function, an async for clause may be used to iterate over a asynchronous iterator. A comprehension in an async def function may consist of either a for or async for clause following the leading expression, may contain additional for or async for clauses, and may also use await expressions.

If a comprehension contains async for clauses, or if it contains await expressions or other asynchronous comprehensions anywhere except the iterable expression in the leftmost for clause, it is called an asynchronous comprehension. An asynchronous comprehension may suspend the execution of the coroutine function in which it appears. See also PEP 530.

Added in version 3.6: Les compréhensions asynchrones ont été introduites.

Modifié dans la version 3.8: yield et yield from sont interdites dans la portée implicite imbriquée.

Modifié dans la version 3.11: les compréhensions asynchrones sont maintenant autorisées dans les compréhensions des fonctions asynchrones. Les compréhensions englobantes deviennent implicitement asynchrones.

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 mutable, 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       ::=  "{" [dict_item_list | dict_comprehension] "}"
dict_item_list     ::=  dict_item ("," dict_item)* [","]
dict_item          ::=  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 valeur 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.

Added in 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 mutables). 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.

Modifié dans la version 3.8: Avant Python 3.8, dans les compréhensions de dictionnaires, l'ordre d'évaluation entre les clés et les valeurs n'était pas bien défini. Dans CPython, la valeur était évaluée avant la clé. À partir de la version 3.8, la clé est évaluée avant la valeur, comme proposé par la PEP 572.

6.2.8. Expressions génératrices

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

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

Une expression génératrice 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ératrice 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.

Pour éviter d'interférer avec l'opération attendue de l'expression génératrice elle-même, les expressions yield et yield from sont interdites dans les générateurs définis de manière implicite.

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

Added in version 3.6: les expressions génératrices asynchrones ont été introduites.

Modifié dans la version 3.7: Avant Python 3.7, les expressions génératrices 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ératrices asynchrones.

Modifié dans la version 3.8: yield et yield from sont interdites dans la portée implicite imbriquée.

6.2.9. Expressions yield

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

Une expression yield est utilisée pour définir une fonction génératrice ou une fonction génératrice 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 une fonction génératrice et son utilisation dans le corps d'une fonction async def entraine que cette fonction coroutine devient une fonction génératrice asynchrone. Par exemple :

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

async def agen(): # defines an asynchronous generator function
    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ératrices.

Modifié dans la version 3.8: Les expressions yield sont interdites dans la portée implicite imbriquée utilisée dans l'implémentation des compréhensions et des expressions génératrices.

Les fonctions génératrices 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ératrices asynchrones.

Lorsqu'une fonction génératrice 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ératrice. 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 ou None si expression_list est omis. 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 (généralement 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ératrices 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ératrice 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'expression passée à yield from <expr> doit être un itérateur. Toutes les valeurs produites par cet 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'affectation.

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.

PEP 525 : Générateurs asynchrones

La proposition qui a amélioré la PEP 492 en ajoutant des capacités de générateur pour les coroutines.

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ératrices.

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ératrice ou la reprend à la dernière expression yield exécutée. Quand une fonction génératrice 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ératrice. 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(value)
generator.throw(type[, value[, traceback]])

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

Dans son utilisation typique, elle est appelée avec une seule instance d'exception, de façon similaire à l'utilisation du mot-clé raise.

Cependant, pour assurer la rétrocompatibilité, la deuxième signature est prise en charge, suivant une convention des anciennes versions de Python. L'argument type doit être une classe d'exception et value doit être une instance d'exception. Si value n'est pas fournie, le constructeur de type est appelé pour obtenir une instance. Si traceback est fournie, elle est liée sur l'exception, sinon tout attribut __traceback__ existant stocké dans value est possiblement effacé.

Modifié dans la version 3.12: The second signature (type[, value[, traceback]]) is deprecated and may be removed in a future version of Python.

generator.close()

Lève une GeneratorExit à l'endroit où la fonction génératrice a été mise en pause. Si la fonction génératrice 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ératrices :

>>> 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ératrices 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ératrice 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ératrice. 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.

Si un générateur asynchrone se termine précipitamment en raison d'un break, de l'annulation de la tâche de l'appelant ou d'une exception, le code de nettoyage du générateur asynchrone est exécuté et lève possiblement des exceptions, accède à des variables de contexte dans un contexte inattendu — peut-être parce que la tâche de laquelle il dépend est finie, ou pendant la fermeture de la boucle d'événements quand le point d'entrée du ramasse-miettes a déjà été appelé. Afin d'éviter cette situation, l'appelant doit explicitement fermer le générateur asynchrone en appelant la méthode aclose() pour « finaliser » le générateur et le détacher de la boucle d'événements.

Dans une fonction génératrice 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ératrice 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ératrices.

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ératrice 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ératrice 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(value)
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ératrice 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ératrice 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.

Modifié dans la version 3.12: The second signature (type[, value[, traceback]]) is deprecated and may be removed in a future version of Python.

coroutine agen.aclose()

Renvoie un awaitable qui, quand il s'exécute, lève une exception GeneratorExit dans la fonction génératrice asynchrone à l'endroit où le générateur était en pause. Si la fonction génératrice 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

The primary must evaluate to an object of a type that supports attribute references, which most objects do. This object is then asked to produce the attribute whose name is the identifier. The type and value produced is determined by the object. Multiple evaluations of the same attribute reference may yield different objects.

This production can be customized by overriding the __getattribute__() method or the __getattr__() method. The __getattribute__() method is called first and either returns a value or raises AttributeError if the attribute is not available.

If an AttributeError is raised and the object has a __getattr__() method, that method is called as a fallback.

6.3.2. sélection (ou indiçage)

L'indiçage d'une instance de classe conteneur sélectionne généralement un élément du conteneur. L'indiçage d'une classe générique renvoie généralement un objet GenericAlias.

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

Lorsqu'on accède à l'indice d'un objet, l'interpréteur évalue la primaire et la liste d'expressions.

L'évaluation de la primaire doit produire un objet qui gère l'indiçage. Un objet est susceptible de gérer l'indiçage s'il définit la ou les deux méthodes __getitem__() et __class_getitem__(). Quand on spécifie un indice du primaire, le résultat de l'évaluation de la liste d'expression est passé à l'une de ces méthodes. Pour plus de détails sur le choix de __class_getitem__ ou __getitem__ pour l'appel, lisez __class_getitem__ contre __getitem__.

Si la liste d'expressions contient au moins une virgule, elle est considérée comme un n-uplet contenant les éléments de la liste d'expressions. Sinon, la liste d'expressions est évaluée à la valeur du seul membre de la liste.

Pour les objets natifs, deux types d'objets gèrent la sélection via __getitem__() :

  1. 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é. Un exemple de classe implémentant le concept de tableau de correspondances est la classe dict.

  2. 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). Des exemples de classes natives implémentant le concept de séquence sont les chaînes, listes et les n-uplets.

The formal syntax makes no special provision for negative indices in sequences. However, built-in sequences all provide a __getitem__() method that interprets negative indices by adding the length of the sequence to the index so that, for example, x[-1] selects the last item of x. The resulting value must be a nonnegative integer less than the number of items in the sequence, and the subscription selects the item whose index is that value (counting from zero). Since the support for negative indices and slicing occurs in the object's __getitem__() method, subclasses overriding this method will need to explicitly add that support.

Une chaîne est une espèce particulière de séquence dont les éléments 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 affectations 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).

The semantics for a slicing are as follows. The primary is indexed (using the same __getitem__() method as normal subscription) with a key that is constructed from the slice list, as follows. If the slice list contains at least one comma, the key is a tuple containing the conversion of the slice items; otherwise, the conversion of the lone slice item is the key. The conversion of a slice item that is an expression is that expression. The conversion of a proper slice is a slice object (see section Hiérarchie des types standards) whose start, stop and step attributes are the values of the expressions given as lower bound, upper bound and stride, respectively, substituting None for missing expressions.

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 ::=  positional_item ("," positional_item)*
positional_item      ::=  assignment_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 nommés, mais elle n'affecte pas la sémantique.

The primary must evaluate to a callable object (user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and all objects having a __call__() method are callable). All argument expressions are evaluated before the call is attempted. Please refer to section Définition de fonctions for the syntax of formal parameter lists.

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 nommé, 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, l'argument est placé 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 fournis comme arguments nommés. 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'argument positionnel en trop).

Si un argument nommé 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 nommés 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 nommé 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 y1yM, c'est équivalent à un appel avec M+4 arguments positionnels x1, x2, y1yM, x3, x4.

Une conséquence est que bien que la syntaxe *expression puisse apparaître après les arguments par nommés explicites, ils sont traités avant les arguments nommé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 rare.

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 paramètre correspondant à une clé a déjà été fourni (en tant qu'argument nommé explicite, en provenance d'un autre dépaquetage), une exception TypeError est levée.

Lorsque **expression est utilisée, chaque clé de ce tableau de correspondances doit être une chaîne. Chaque valeur du tableau est affectée au premier paramètre formel éligible à l'affectation par mot-clé dont le nom est égal à la clé. Une clé n'a pas besoin d'être un identifiant Python (par exemple, "max-temp °F" est acceptable, bien qu'elle ne corresponde à aucun paramètre formel qui pourrait être déclaré). S'il n'y a pas de correspondance avec un paramètre formel, la paire clé-valeur est collectée par le paramètre **, s'il y en a un. S'il n'y a pas de paramètre **, 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 :

The class must define a __call__() method; the effect is then the same as if that method was called.

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

Added in 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).

This operation can be customized using the special __pow__() and __rpow__() methods.

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

The unary - (minus) operator yields the negation of its numeric argument; the operation can be overridden with the __neg__() special method.

The unary + (plus) operator yields its numeric argument unchanged; the operation can be overridden with the __pos__() special method.

The unary ~ (invert) operator yields the bitwise inversion of its integer argument. The bitwise inversion of x is defined as -(x+1). It only applies to integral numbers or to custom objects that override the __invert__() special method.

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.

This operation can be customized using the special __mul__() and __rmul__() methods.

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

This operation can be customized using the special __matmul__() and __rmatmul__() methods.

Added in version 3.5.

Les opérateurs / (division) et // (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.

The division operation can be customized using the special __truediv__() and __rtruediv__() methods. The floor division operation can be customized using the special __floordiv__() and __rfloordiv__() methods.

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.

The modulo operation can be customized using the special __mod__() and __rmod__() methods.

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.

This operation can be customized using the special __add__() and __radd__() methods.

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

This operation can be customized using the special __sub__() and __rsub__() methods.

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.

The left shift operation can be customized using the special __lshift__() and __rlshift__() methods. The right shift operation can be customized using the special __rshift__() and __rrshift__() methods.

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

The & operator yields the bitwise AND of its arguments, which must be integers or one of them must be a custom object overriding __and__() or __rand__() special methods.

The ^ operator yields the bitwise XOR (exclusive OR) of its arguments, which must be integers or one of them must be a custom object overriding __xor__() or __rxor__() special methods.

The | operator yields the bitwise (inclusive) OR of its arguments, which must be integers or one of them must be a custom object overriding __or__() or __ror__() special methods.

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 donnent des valeurs booléennes (True ou False). Cependant, les méthodes de comparaison riche définies par l'utilisateur peuvent renvoyer des non-booléens. Dans ce cas, le résultat de la comparaison est converti en booléen avec bool() dans les contextes qui attendent un booléen.

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, cy, z sont des expressions et op1, op2opN 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 chapitre 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.

Because all types are (direct or indirect) subtypes of object, they inherit the default comparison behavior from object. Types can customize their comparison behavior by implementing rich comparison methods like __lt__(), described in 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 non numériques float('NaN') et decimal.Decimal('NaN') sont spéciales : toute comparaison entre un nombre et une valeur non numérique est fausse. Une implication contre-intuitive à cela est que les valeurs non numériques ne sont pas égales à elles-mêmes. Par exemple, avec x = float('NaN'), les expressions 3 < x, x < 3 et x == x sont toutes fausses, mais l’expression x != x est vraie. Ce comportement est en accord avec IEEE 754.

  • None and NotImplemented are singletons. PEP 8 advises that comparisons for singletons should always be done with is or is not, never the equality operators.

  • 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 se comparent lexicographiquement en comparant les éléments correspondants. Les conteneurs natifs supposent généralement que les objets identiques sont égaux à eux-mêmes. Cela leur permet d'économiser les tests d’égalité pour des objets identiques afin d’améliorer les performances et de conserver leurs invariants internes.

    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 définies par l'utilisateur 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, cela doit en produire la négation booléenne. En d'autres termes, les expressions suivantes doivent produire le même résultat :

    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 figé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.

For user-defined classes which define the __contains__() method, x in y returns True if y.__contains__(x) returns a true value, and False otherwise.

For user-defined classes which do not define __contains__() but do define __iter__(), x in y is True if some value z, for which the expression x is z or x == z is true, is produced while iterating over y. If an exception is raised during the iteration, it is as if in raised that exception.

Lastly, the old-style iteration protocol is tried: if a class defines __getitem__(), x in y is True if and only if there is a non-negative integer index i such that x is y[i] or x == y[i], and no lower integer index raises the IndexError exception. (If any other exception is raised, it is as if in raised that 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

In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true. User-defined objects can customize their truth value by providing a __bool__() method.

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 d'affectation

assignment_expression ::=  [identifier ":="] expression

Une expression d'affectation (parfois aussi appelée « expression nommée » ou « expression morse ») affecte l'expression à un identifiant et renvoie la valeur de l'expression.

Une utilisation classique concerne les correspondances d'expressions rationnelles :

if matching := pattern.search(data):
    do_something(matching)

Ou lorsqu'on traite le contenu d'un fichier par morceaux :

while chunk := file.read(9000):
    process(chunk)

Assignment expressions must be surrounded by parentheses when used as expression statements and when used as sub-expressions in slicing, conditional, lambda, keyword-argument, and comprehension-if expressions and in assert, with, and assignment statements. In all other places where they can be used, parentheses are not required, including in if and while statements.

Added in version 3.8: Voir la PEP 572 pour plus de détails sur les expressions d’affectation.

6.13. Expressions conditionnelles

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

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.14. Expressions lambda

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

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.15. Listes d'expressions

expression_list    ::=  expression ("," expression)* [","]
starred_list       ::=  starred_item ("," starred_item)* [","]
starred_expression ::=  expression | (starred_item ",")* [starred_item]
starred_item       ::=  assignment_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. 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 n-uplet, liste ou ensemble à l'emplacement du dépaquetage.

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

A trailing comma is required only to create a one-item tuple, such as 1,; it is optional in all other cases. A single expression without a trailing comma doesn't create a tuple, but rather yields the value of that expression. (To create an empty tuple, use an empty pair of parentheses: ().)

6.16. Ordre d'évaluation

Python évalue les expressions de la gauche vers la droite. Remarquez que lors de l'évaluation d'une affectation, la partie droite de l'affectation 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.17. Priorités des opérateurs

Le tableau suivant résume les priorités des opérateurs en Python, du plus prioritaire (portée la plus courte) au moins prioritaire (portée la plus grande). 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 case regroupent de la gauche vers la droite (sauf pour la puissance et les expressions conditionnelles qui regroupent 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

(expressions…),

[expressions…], {key: value…}, {expressions…}

Expression de liaison ou parenthèse, affichage de liste, affichage de dictionnaire, affichage de set

x[indice], x[indice:indice], x(arguments…), x.attribut

indiçage, tranches, appel, référence à un attribut

await x

Expression await

**

Puissance [5]

+x, -x, ~x

NOT (positif, négatif, bit à bit)

*, @, /, //, %

Multiplication, multiplication de matrices, division, division entière, reste [6]

+, -

Addition et soustraction

<<, >>

décalages

&

AND (bit à bit)

^

XOR (bit à bit)

|

OR (bit à bit)

in, not in, is, is not, <, <=, >, >=, !=, ==

Comparaisons, y compris les tests d'appartenance et les tests d'identifiants

not x

NOT (booléen)

and

AND (booléen)

or

OR (booléen)

if -- else

Expressions conditionnelles

lambda

Expression lambda

:=

Expression d'affectation

Notes