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.
Notez que la compréhension est exécutée dans une portée séparée, les noms assignés dans la liste cible ne pouvant pas « fuir » en dehors de cette portée.
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 suspendre l’exécution de la fonction coroutine dans laquelle elle apparaît. Voir aussi la PEP 530.
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. 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é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, la clause for
la plus à gauche est immédiatement évaluée, de manière à ce qu’une erreur dans cette partie puisse être vue avant tout autre erreur dans le code qui gère l’expression générateur. Les clauses for
suivantes ne peuvent pas être évaluées immédiatement car elles peuvent dépendre de la précédente boucle for
. Par exemple, (x*y for x in range(10) for y in truc(x))
.
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.
Depuis Python 3.6, si le générateur apparaît dans une fonction async def
, alors la clause async for
et les expressions await
sont permises comme pour une compréhension asynchrone. Si une expression générateur contient soit des clauses async for
, soit des expressions await
, alors on l’appelle expression générateur asynchrone. Une expression générateur asynchrone produit un nouvel objet générateur asynchrone qui est un itérateur asynchrone (voir Itérateurs asynchrones).
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é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 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
yield 123
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. 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é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’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.- PEP 525 - Asynchronous Generators
The proposal that expanded on PEP 492 by adding generator capabilities to coroutine functions.
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’expressionyield
en cours s’évalue toujours àNone
. L’exécution continue ensuite jusqu’à l’expressionyield
suivante, où le générateur est à nouveau suspendu et la valeur deexpression_list
est renvoyée à la méthode__next__()
de l’appelant. Si le générateur termine sans donner une autre valeur, une exceptionStopIteration
est levée.Cette méthode est normalement appelée implicitement, par exemple par une boucle
for
ou par la fonction nativenext()
.
-
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éthodesend()
renvoie la valeur suivante produite par le générateur ou lèveStopIteration
si le générateur termine sans produire de nouvelle valeur. Quandsend()
est utilisée pour démarrer le générateur, elle doit avoirNone
comme argument, car il n’y a aucune expressionyield
qui peut recevoir la valeur.
-
generator.
throw
(type[, value[, traceback]])¶ Lève 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 exceptionStopIteration
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.
-
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èveGeneratorExit
(parce qu’elle ne gère pas l’exception), close revient vers l’appelant. Si le générateur produit une valeur, uneRuntimeError
est levée. Si le générateur lève une autre exception, elle est propagée à l’appelant. La méthodeclose()
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.
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é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érateur asynchrone est reprise par une méthode__anext__()
, l’expressionyield
en cours s’évalue toujours àNone
dans le awaitable renvoyé, et elle continue son exécution jusqu’à l’expressionyield
suivante. La valeur deexpression_list
de l’expressionyield
est la valeur de l’exceptionStopIteration
levée par la coroutine qui termine. Si le générateur asynchrone termine sans produire d’autre valeur, le awaitable lève une exceptionStopAsyncIteration
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’expressionyield
courante. Le awaitable renvoyé par la méthodeasend()
renvoie la valeur suivante produite par le générateur comme valeur de l’exceptionStopIteration
levée ou lèveStopAsyncIteration
si le générateur asynchrone termine sans produire de nouvelle valeur. Quandasend()
est appelée pour démarrer le générateur asynchrone, l’argument doit êtreNone
car il n’y a pas d’expressionyield
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’exceptionStopIteration
qui a été levée. Si le générateur asynchrone termine sans produire de nouvelle valeur, une exceptionStopAsyncIteration
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é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èveGeneratorExit
(parce qu’elle ne gère pas l’exception), alors le awaitable renvoyé lève une exceptionStopIteration
. Tout nouveau awaitable produit par un appel postérieur au générateur asynchrone lève une exceptionStopAsyncIteration
. Si le générateur asynchrone produit une valeur, uneRuntimeError
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.
CPython implementation detail: 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 @
(prononcé at en anglais) 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) 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
.
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)
.
Note
Dans l’implémentation actuelle, l’opérande de droite doit être au maximum sys.maxsize
. Si l’opérande de droite est plus grand que sys.maxsize
, une exception OverflowError
est levée.
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 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.
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 quedecimal.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')
etDecimal('NaN')
, ont un traitement spécial.Les séquences binaires (instances du type
bytes
oubytearray
) 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 nativeord()
) 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
ourange
) 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 uneTypeError
.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 quex <= 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èventTypeError
.Les ensembles (instances de
set
oufrozenset
) 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 fonctionsmin()
,max()
etsorted()
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
impliquex == y
La comparaison doit être symétrique. En d’autres termes, les expressions suivantes doivent donner le même résultat :
x == y
ety == x
x != y
ety != x
x < y
ety > x
x <= y
ety >= x
La comparaison doit être transitive. Les exemples suivants (liste non exhaustive) illustrent ce concept :
x > y and y > z
impliquex > z
x < y and y <= z
impliquex < 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
etnot x != y
x < y
etnot x >= y
(pour une relation d’ordre total)x > y
etnot 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.
Note that neither and
nor or
restrict the value and type
they return to False
and True
, but rather return the last evaluated
argument. This is sometimes useful, e.g., if s
is a string that should be
replaced by a default value if it is empty, the expression s or 'foo'
yields
the desired value. Because not
has to create a new value, it
returns a boolean value regardless of the type of its argument
(for example, not 'foo'
produces False
rather than ''
.)
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 |
---|---|
Expression lambda |
|
Expressions conditionnelle |
|
OR (booléen) |
|
AND (booléen) |
|
|
NOT (booléen) |
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 |
|
NOT (positif, négatif, bit à bit) |
|
Puissance 6 |
|
Expression |
|
indiçage, tranches, appel, référence à un attribut |
|
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 que1e100
, le résultat calculé est-1e-100 + 1e100
, qui vaut exactement1e100
dans ce standard. Or, la fonctionmath.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’avoirdivmod(x,y)[0] * y + x % y
le plus proche dex
.- 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"
renvoieFalse
, 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
vaut0.5
.