3. Modèle de données
********************


3.1. Objets, valeurs et types
=============================

En Python, les données sont représentées sous forme *d'objets*. Toutes
les données d'un programme Python sont représentées par des objets ou
par des relations entre les objets (dans un certain sens, et en
conformité avec le modèle de Von Neumann d'« ordinateur à programme
enregistré », le code est aussi représenté par des objets).

Chaque objet possède un identifiant, un type et une valeur.
*L'identifiant* d'un objet ne change jamais après sa création ; vous
pouvez vous le représenter comme l'adresse de l'objet en mémoire.
L'opérateur "is" compare les identifiants de deux objets ; la fonction
"id()" renvoie un entier représentant cet identifiant.

**CPython implementation detail:** en CPython, "id(x)" est l'adresse
mémoire où est stocké "x".

Le type de l'objet détermine les opérations que l'on peut appliquer à
l'objet (par exemple, « a-t-il une longueur ? ») et définit aussi les
valeurs possibles pour les objets de ce type. La fonction "type()"
renvoie le type de l'objet (qui est lui-même un objet). Comme
l'identifiant, le *type* d'un objet ne peut pas être modifié [1].

La *valeur* de certains objets peut changer. Les objets dont la valeur
peut changer sont dits *muables* (*mutable* en anglais) ; les objets
dont la valeur est définitivement fixée à leur création sont dits
*immuables* (*immutable* en anglais). La valeur d'un objet conteneur
immuable qui contient une référence vers un objet muable peut varier
lorsque la valeur de l'objet muable change ; cependant, le conteneur
est quand même considéré comme immuable parce que l'ensemble des
objets qu'il contient ne peut pas être modifié. Ainsi, l'immuabilité
n'est pas strictement équivalente au fait d'avoir une valeur non
modifiable, c'est plus subtil. La muabilité d'un objet est définie par
son type ; par exemple, les nombres, les chaînes de caractères et les
*n*-uplets sont immuables alors que les dictionnaires et les listes
sont muables.

Un objet n'est jamais explicitement détruit ; cependant, lorsqu'il ne
peut plus être atteint, il a vocation à être supprimé par le ramasse-
miettes (*garbage-collector* en anglais). L'implémentation peut
retarder cette opération ou même ne pas la faire du tout — la façon
dont fonctionne le ramasse-miette est particulière à chaque
implémentation, l'important étant qu'il ne supprime pas d'objet qui
peut encore être atteint.

**CPython implementation detail:** CPython utilise aujourd'hui un
mécanisme de compteur de références avec une détection, en temps
différé et optionnelle, des cycles d'objets. Ce mécanisme supprime la
plupart des objets dès qu'ils ne sont plus accessibles mais il ne
garantit pas la suppression des objets où il existe des références
circulaires. Consultez la documentation du module "gc" pour tout ce
qui concerne la suppression des cycles. D'autres implémentations
agissent différemment et CPython pourrait évoluer. Ne vous reposez pas
sur la finalisation immédiate des objets devenus inaccessibles (ainsi,
vous devez toujours fermer les fichiers explicitement).

Notez que si vous utilisez les fonctionnalités de débogage ou de trace
de l'implémentation, il est possible que des références qui seraient
normalement supprimées soient toujours présentes. Notez aussi que
capturer une exception avec l'instruction "try"…"except" peut
conserver des objets en vie.

Certains objets font référence à des ressources « externes » telles
que des fichiers ouverts ou des fenêtres. Ces objets libèrent ces
ressources au moment où ils sont supprimés, mais comme le ramasse-
miettes ne garantit pas qu'il supprime tous les objets, ces objets
fournissent également un moyen explicite de libérer la ressource
externe, généralement sous la forme d'une méthode "close()". Nous
incitons fortement les programmeurs à fermer explicitement de tels
objets. Les instructions "try"…"finally" et "with" sont très pratiques
pour cela.

Certains objets contiennent des références à d'autres objets ; on les
appelle *conteneurs*. Comme exemples de conteneurs, nous pouvons citer
les *n*-uplets, les listes et les dictionnaires. Les références sont
parties intégrantes de la valeur d'un conteneur. Dans la plupart des
cas, lorsque nous parlons de la valeur d'un conteneur, nous parlons
des valeurs, pas des identifiants des objets contenus ; cependant,
lorsque nous parlons de la muabilité d'un conteneur, seuls les
identifiants des objets immédiatement contenus sont concernés. Ainsi,
si un conteneur immuable (comme un *n*-uplet) contient une référence à
un objet muable, sa valeur change si cet objet muable est modifié.

Presque tous les comportements d'un objet dépendent du type de
l'objet. Même son identifiant est concerné dans un certain sens : pour
les types immuables, les opérations qui calculent de nouvelles valeurs
peuvent en fait renvoyer une référence à n'importe quel objet existant
avec le même type et la même valeur, alors que pour les objets muables
cela n'est pas autorisé. Par exemple, après "a = 1 ; b = 1", "a" et
"b" peuvent ou non se référer au même objet avec la valeur un, en
fonction de l'implémentation. Mais après "c = [] ; d = []", il est
garanti que "c" et "d" font référence à deux listes vides distinctes
nouvellement créées. Notez que "c = d = []" attribue le même objet à
"c" et "d".


3.2. Hiérarchie des types standards
===================================

Vous trouvez ci-dessous une liste des types natifs de Python. Des
modules d'extension (écrits en C, Java ou d'autres langages) peuvent
définir des types supplémentaires. Les futures versions de Python
pourront ajouter des types à cette hiérarchie (par exemple les nombres
rationnels, des tableaux d'entiers stockés efficacement, etc.), bien
que de tels ajouts se trouvent souvent plutôt dans la bibliothèque
standard.

Quelques descriptions des types ci-dessous contiennent un paragraphe
listant des « attributs spéciaux ». Ces attributs donnent accès à
l'implémentation et n'ont, en général, pas vocation à être utilisés.
Leur définition peut changer dans le futur.

"None"
   Ce type ne possède qu'une seule valeur. Il n'existe qu'un seul
   objet avec cette valeur. Vous accédez à cet objet avec le nom natif
   "None". Il est utilisé pour signifier l'absence de valeur dans de
   nombreux cas, par exemple pour des fonctions qui ne retournent rien
   explicitement. Sa valeur booléenne est fausse.

NotImplemented
   Ce type ne possède qu'une seule valeur. Il n'existe qu'un seul
   objet avec cette valeur. Vous accédez à cet objet avec le nom natif
   "NotImplemented". Les méthodes numériques et les comparaisons
   riches doivent renvoyer cette valeur si elles n'implémentent pas
   l'opération pour les opérandes fournis (l'interpréteur essaie alors
   l'opération en permutant les opérandes ou tout autre stratégie de
   contournement, en fonction de l'opérateur). Il ne doit pas être
   évalué dans un contexte booléen.

   Consultez Implémentation des opérations arithmétiques pour
   davantage de détails.

   Modifié dans la version 3.9: évaluer "NotImplemented" dans un
   contexte booléen est obsolète. Python l'évalue aujourd'hui à "True"
   mais émet un "DeprecationWarning". Il lèvera une "TypeError" dans
   une version ultérieure de Python.

Ellipse
   Ce type ne possède qu'une seule valeur. Il n'existe qu'un seul
   objet avec cette valeur. Vous accédez à cet objet avec le littéral
   "..." ou le nom natif "Ellipsis". Sa valeur booléenne est vraie.

"numbers.Number"
   Ces objets sont créés par les littéraux numériques et renvoyés en
   tant que résultats par les opérateurs et les fonctions
   arithmétiques natives. Les objets numériques sont immuables ; une
   fois créés, leur valeur ne change pas. Les nombres Python sont bien
   sûr très fortement corrélés aux nombres mathématiques mais ils sont
   soumis aux limitations des représentations numériques par les
   ordinateurs.

   Les représentations sous forme de chaînes de caractères des objets
   numériques, produites par "__repr__()" et "__str__()", ont les
   propriétés suivantes :

   * Ce sont des littéraux numériques valides qui, s'ils sont passés
     au constructeur de leur classe, produisent un objet qui a la
     valeur numérique de l'objet d'origine.

   * La représentation est en base 10, si possible.

   * Les zéros en tête, sauf en ce qui concerne un zéro seul avant la
     virgule (représentée par un point en Python conformément à la
     convention anglo-saxonne), ne sont pas affichés.

   * Les zéros en fin, sauf en ce qui concerne un zéro seul après la
     virgule, ne sont pas affichés.

   * Le signe n'est affiché que lorsque le nombre est négatif.

   Python distingue les entiers, les nombres à virgule flottante et
   les nombres complexes :

   "numbers.Integral"
      Ils représentent des éléments de l'ensemble mathématique des
      entiers (positifs ou négatifs).

      Il existe deux types d'entiers :

      Entiers ("int")
         Ils représentent les nombres, sans limite de taille, sous
         réserve de pouvoir être stockés en mémoire (virtuelle). Afin
         de pouvoir effectuer des décalages et appliquer des masques,
         on considère qu'ils ont une représentation binaire. Les
         nombres négatifs sont représentés comme une variante du
         complément à 2, qui donne l'illusion d'une chaîne infinie de
         bits de signe s'étendant vers la gauche.

      Booléens ("bool")
         Ils représentent les valeurs *faux* et *vrai*. Deux objets,
         "False" et "True", sont les seuls objets booléens. Le type
         booléen est un sous-type du type entier et les valeurs
         booléennes se comportent comme les valeurs 0 (pour "False")
         et 1 (pour "True") dans presque tous les contextes.
         L'exception concerne la conversion en chaîne de caractères où
         ""False"" et ""True"" sont renvoyées.

      Les règles pour la représentation des entiers ont pour objet de
      donner l'interprétation la plus naturelle pour les opérations de
      décalage et masquage qui impliquent des entiers négatifs.

   "numbers.Real" ("float")
      Ils représentent les nombres à virgule flottante en double
      précision, tels que manipulés directement par la machine. Vous
      dépendez donc de l'architecture machine sous-jacente (et de
      l'implémentation C ou Java) pour les intervalles gérés et le
      traitement des débordements. Python ne gère pas les nombres à
      virgule flottante en précision simple ; les gains en puissance
      de calcul et mémoire, qui sont généralement la raison de
      l'utilisation des nombres en simple précision, sont annihilés
      par le fait que Python encapsule de toute façon ces nombres dans
      des objets. Il n'y a donc aucune raison de compliquer le langage
      avec deux types de nombres à virgule flottante.

   "numbers.Complex" ("complex")
      Ils représentent les nombres complexes, sous la forme d'un
      couple de nombres à virgule flottante en double précision, tels
      que manipulés directement par la machine. Les mêmes restrictions
      s'appliquent que pour les nombres à virgule flottante. La partie
      réelle et la partie imaginaire d'un nombre complexe "z" peuvent
      être demandées par les attributs en lecture seule "z.real" et
      "z.imag".

Séquences
   Ils représentent des ensembles de taille finie indicés par des
   entiers positifs ou nuls. La fonction native "len()" renvoie le
   nombre d'éléments de la séquence. Quand la longueur d'une séquence
   est *n*, l'ensemble des indices contient les entiers 0, 1 …, *n-1*.
   On accède à l'élément d'indice *i* de la séquence *a* par "a[i]".

   Les séquences peuvent aussi être découpées en tranches (*slicing*
   en anglais) : "a[i:j]" sélectionne tous les éléments d'indice *k*
   tel que *i* "<=" *k* "<" *j*. Quand on l'utilise dans une
   expression, la tranche est du même type que la séquence. Ceci veut
   dire que l'ensemble des indices de la tranche est renuméroté de
   manière à partir de 0.

   Quelques séquences gèrent le « découpage étendu » (*extended
   slicing* en anglais) avec un troisième paramètre : "a[i:j:k]"
   sélectionne tous les éléments de *a* d'indice *x* où "x = i + n*k",
   avec *n* ">=" "0" et *i* "<=" *x* "<" *j*.

   Les séquences se différencient en fonction de leur muabilité :

   Séquences immuables
      Un objet de type de séquence immuable ne peut pas être modifié
      une fois qu'il a été créé. Si l'objet contient des références à
      d'autres objets, ces autres objets peuvent être muables et
      peuvent être modifiés ; cependant, les objets directement
      référencés par un objet immuable ne peuvent pas être modifiés.

      Les types suivants sont des séquences immuables :

      Chaînes de caractères
         Une chaîne de caractères (*string* en anglais) est une
         séquence de valeurs qui représentent des caractères Unicode.
         Tout caractère dont le code est dans l'intervalle "U+0000 -
         U+10FFFF" peut être représenté dans une chaîne. Python ne
         possède pas de type "char" ; à la place, chaque caractère
         Unicode dans la chaîne est représenté par un objet chaîne de
         longueur "1". La fonction native "ord()" convertit un
         caractère Unicode de la représentation en chaîne vers un
         entier dans l'intervalle "0 - 10FFFF" ; la fonction "chr()"
         convertit un entier de l'intervalle "0 - 10FFFF" vers l'objet
         chaîne de longueur "1" correspondant. "str.encode()" peut
         être utilisée pour convertir un objet "str" vers "bytes"
         selon l'encodage spécifié et "bytes.decode()" effectue
         l'opération inverse.

      *n*-uplets (*tuples* en anglais)
         Les éléments d'un *n*-uplet peuvent être n'importe quel objet
         Python. Les *n*-uplets de deux éléments ou plus sont formés
         par une liste d'expressions dont les éléments sont séparés
         par des virgules. Un *n*-uplet composé d'un seul élément (un
         « singleton ») est formé en suffixant une expression avec une
         virgule (une expression en tant que telle ne crée pas un
         *n*-uplet car les parenthèses doivent rester disponibles pour
         grouper les expressions). Un *n*-uplet vide est formé à
         l'aide d'une paire de parenthèses vide.

      Chaînes d'octets (ou *bytes*)
         Les objets *bytes* sont des tableaux immuables. Les éléments
         sont des octets (donc composés de 8 bits), représentés par
         des entiers dans l'intervalle 0 à 255 inclus. Les littéraux
         *bytes* (tels que "b'abc'") et la fonction native
         constructeur "bytes()" peuvent être utilisés pour créer des
         objets *bytes*. Aussi, un objet *bytes* peut être décodé vers
         une chaîne *via* la méthode "decode()".

   Séquences muables
      Les séquences muables peuvent être modifiées après leur
      création. Les notations de tranches et de sous-ensembles peuvent
      être utilisées en tant que cibles d'une assignation ou de
      l'instruction "del" (suppression).

      Il existe aujourd'hui deux types intrinsèques de séquences
      muables :

      Listes
         N'importe quel objet Python peut être élément d'une liste.
         Les listes sont créées en plaçant entre crochets une liste
         d'expressions dont les éléments sont séparés par des virgules
         (notez que les listes de longueur 0 ou 1 ne sont pas des cas
         particuliers).

      Tableaux d'octets
         Un objet *bytearray* est un tableau muable. Il est créé par
         la fonction native constructeur "bytearray()". À part la
         propriété d'être muable (et donc de ne pas pouvoir calculer
         son empreinte par hachage), un tableau d'octets possède la
         même interface et les mêmes fonctionnalités qu'un objet
         immuable "bytes".

      Le module d'extension "array" fournit un autre exemple de type
      de séquence muable, de même que le module "collections".

Ensembles
   Ils représentent les ensembles d'objets, non ordonnés, finis et
   dont les éléments sont uniques. Tels quels, ils ne peuvent pas être
   indicés. Cependant, il est possible d'itérer dessus et la fonction
   native "len()" renvoie le nombre d'éléments de l'ensemble. Les
   utilisations classiques des ensembles sont les tests d'appartenance
   rapides, la suppression de doublons dans une séquence et le calcul
   d'opérations mathématiques telles que l'intersection, l'union, la
   différence et le complémentaire.

   Pour les éléments des ensembles, les mêmes règles concernant
   l'immuabilité s'appliquent que pour les clés de dictionnaires.
   Notez que les types numériques obéissent aux règles normales pour
   les comparaisons numériques : si deux nombres sont égaux (pour
   l'opération de comparaison, par exemple "1" et "1.0"), un seul
   élément est conservé dans l'ensemble.

   Actuellement, il existe deux types d'ensembles natifs :

   Ensembles
      Ils représentent les ensembles muables. Un ensemble est créé par
      la fonction native constructeur "set()" et peut être modifié par
      la suite à l'aide de différentes méthodes, par exemple "add()".

   Ensembles figés
      Ils représentent les ensembles immuables. Ils sont créés par la
      fonction native constructeur "frozenset()". Comme un ensemble
      figé est immuable et *hachable*, il peut être utilisé comme
      élément d'un autre ensemble ou comme clé de dictionnaire.

Tableaux de correspondances
   Ils représentent les ensembles finis d'objets indicés par des
   ensembles index arbitraires. La notation "a[k]" sélectionne
   l'élément indicé par "k" dans le tableau de correspondance "a" ;
   elle peut être utilisée dans des expressions, comme cible d'une
   assignation ou avec l'instruction "del". La fonction native "len()"
   renvoie le nombre d'éléments du tableau de correspondances.

   Il n'existe actuellement qu'un seul type natif pour les tableaux de
   correspondances :

   Dictionnaires
      Ils représentent les ensembles finis d'objets indicés par des
      valeurs presque arbitraires. Les seuls types de valeurs non
      reconnus comme clés sont les valeurs contenant des listes, des
      dictionnaires ou les autres types muables qui sont comparés par
      valeur plutôt que par l'identifiant de l'objet. La raison de
      cette limitation est qu'une implémentation efficace de
      dictionnaire requiert que l'empreinte par hachage des clés reste
      constante dans le temps. Les types numériques obéissent aux
      règles normales pour les comparaisons numériques : si deux
      nombres sont égaux pour l'opération de comparaison, par exemple
      "1" et "1.0", alors ces deux nombres peuvent être utilisés
      indifféremment pour désigner la même entrée du dictionnaire.

      Les dictionnaires préservent l’ordre d’insertion, ce qui
      signifie que les clés sont renvoyées séquentiellement dans le
      même ordre que celui de l’insertion. Remplacer une clé existante
      ne change pas l’ordre. Par contre, la retirer puis la réinsérer
      la met à la fin et non à sa précédente position.

      Les dictionnaires sont muables : ils peuvent être créés par la
      notation "{…}" (reportez-vous à la section Agencements de
      dictionnaires).

      Les modules d'extensions "dbm.ndbm" et "dbm.gnu" apportent
      d'autres exemples de types tableaux de correspondances, de même
      que le module "collections".

      Modifié dans la version 3.7: Les dictionnaires ne conservaient
      pas l’ordre d’insertion dans les versions antérieures à Python
      3.6. Dans CPython 3.6, l’ordre d’insertion était déjà conservé,
      mais considéré comme un détail d’implémentation et non comme une
      garantie du langage.

Types appelables
   Ce sont les types sur lesquels on peut faire un appel de fonction
   (lisez la section Appels) :

   Fonctions allogènes
      Un objet fonction allogène (ou fonction définie par
      l'utilisateur, mais ce n'est pas forcément l'utilisateur courant
      qui a défini cette fonction) est créé par la définition d'une
      fonction (voir la section Définition de fonctions). Il doit être
      appelé avec une liste d'arguments contenant le même nombre
      d'éléments que la liste des paramètres formels de la fonction.

      Attributs spéciaux :

      +---------------------------+---------------------------------+-------------+
      | Attribut                  | Signification                   |             |
      |===========================|=================================|=============|
      | "__doc__"                 | Texte de documentation de la    | Accessible  |
      |                           | fonction ou "None" s'il n'en    | en écriture |
      |                           | existe pas ; n'est pas héritée  |             |
      |                           | par les sous-classes.           |             |
      +---------------------------+---------------------------------+-------------+
      | "__name__"                | Nom de la fonction.             | Accessible  |
      |                           |                                 | en écriture |
      +---------------------------+---------------------------------+-------------+
      | "__qualname__"            | *Nom qualifié* de la fonction.  | Accessible  |
      |                           | Nouveau dans la version 3.3.    | en écriture |
      +---------------------------+---------------------------------+-------------+
      | "__module__"              | Nom du module où la fonction    | Accessible  |
      |                           | est définie ou "None" si ce nom | en écriture |
      |                           | n'est pas disponible.           |             |
      +---------------------------+---------------------------------+-------------+
      | "__defaults__"            | Tuple contenant les valeurs des | Accessible  |
      |                           | arguments par défaut pour ceux  | en écriture |
      |                           | qui en sont dotés ou "None" si  |             |
      |                           | aucun argument n'a de valeur    |             |
      |                           | par défaut.                     |             |
      +---------------------------+---------------------------------+-------------+
      | "__code__"                | Objet code représentant le      | Accessible  |
      |                           | corps de la fonction compilée.  | en écriture |
      +---------------------------+---------------------------------+-------------+
      | "__globals__"             | Référence pointant vers le      | Accessible  |
      |                           | dictionnaire contenant les      | en lecture  |
      |                           | variables globales de la        | seule       |
      |                           | fonction — l'espace de noms     |             |
      |                           | global du module dans lequel la |             |
      |                           | fonction est définie.           |             |
      +---------------------------+---------------------------------+-------------+
      | "__dict__"                | Espace de nommage accueillant   | Accessible  |
      |                           | les attributs de la fonction.   | en écriture |
      +---------------------------+---------------------------------+-------------+
      | "__closure__"             | "None" ou *n*-uplet de cellules | Accessible  |
      |                           | qui contient un lien pour       | en lecture  |
      |                           | chaque variable libre de la     | seule       |
      |                           | fonction. Voir ci-dessous pour  |             |
      |                           | les informations relatives à    |             |
      |                           | l'attribut "cell_contents".     |             |
      +---------------------------+---------------------------------+-------------+
      | "__annotations__"         | Dictionnaire contenant les      | Accessible  |
      |                           | annotations des paramètres. Les | en écriture |
      |                           | clés du dictionnaire sont les   |             |
      |                           | noms des paramètres et la clé   |             |
      |                           | ""return"" est utilisée pour    |             |
      |                           | les annotations de la valeur    |             |
      |                           | renvoyée. Les entrées du        |             |
      |                           | dictionnaire ne sont présentes  |             |
      |                           | que si les paramètres sont      |             |
      |                           | effectivement annotés.          |             |
      +---------------------------+---------------------------------+-------------+
      | "__kwdefaults__"          | Dictionnaire contenant les      | Accessible  |
      |                           | valeurs par défaut pour les     | en écriture |
      |                           | paramètres passés par mot-clé.  |             |
      +---------------------------+---------------------------------+-------------+

      La plupart des attributs étiquetés « Accessible en écriture »
      vérifient le type de la valeur qu'on leur assigne.

      Les objets fonctions acceptent également l'assignation et la
      lecture d'attributs arbitraires. Vous pouvez utiliser cette
      fonctionnalité pour, par exemple, associer des métadonnées aux
      fonctions. La notation classique par point est utilisée pour
      définir et lire de tels attributs. *Notez que l'implémentation
      actuelle accepte seulement les attributs de fonction sur les
      fonctions définies par l'utilisateur. Les attributs de fonction
      pour les fonctions natives seront peut-être acceptés dans le
      futur.*

      Un objet cellule possède un attribut "cell_contents". Il peut
      être utilisé pour obtenir la valeur de la cellule et pour en
      définir la valeur.

      Vous trouvez davantage d'informations sur la définition de
      fonctions dans le code de cet objet ; la description des types
      internes est donnée plus bas. Le type "cell" est accessible dans
      le module "types".

   Méthodes d'instances
      Un objet méthode d'instance combine une classe, une instance de
      classe et tout objet appelable (normalement une fonction définie
      par l'utilisateur).

      Attributs spéciaux en lecture seule : "__self__" est l'objet
      instance de classe, "__func__" est l'objet fonction ; "__doc__"
      est la documentation de la méthode (comme "__func__.__doc__") ;
      "__name__" est le nom de la méthode (comme "__func__.__name__")
      ; "__module__" est le nom du module où la méthode est définie ou
      "None" s'il n'est pas disponible.

      Les méthodes savent aussi accéder (mais pas modifier) les
      attributs de la fonction de l'objet fonction sous-jacent.

      Les objets méthodes définies par l'utilisateur peuvent être
      créés quand vous récupérez un attribut de classe (par exemple
      *via* une instance de cette classe) si cet attribut est un objet
      fonction définie par l'utilisateur ou un objet méthode de
      classe.

      Quand un objet méthode d'instance est créé à partir d'un objet
      fonction définie par l'utilisateur *via* une des instances, son
      attribut "__self__" est l'instance et l'objet méthode est réputé
      lié. Le nouvel attribut de la méthode "__func__" est l'objet
      fonction original.

      Quand un objet méthode d'instance est créé à partir d'un autre
      objet méthode de la classe ou de l'instance, son attribut
      "__self__" est la classe elle-même et son attribut "__func__"
      est l'objet fonction sous-jacent la méthode de classe.

      Quand un objet méthode d'instance est appelé, la fonction sous-
      jacente ("__func__") est appelée et l'objet instance de la
      classe ("__self__") est inséré en tête de liste des arguments.
      Par exemple, si "C" est une classe qui contient la définition
      d'une fonction "f()" et que "x" est une instance de "C", alors
      appeler "x.f(1)" est équivalent à appeler "C.f(x, 1)".

      Quand un objet méthode d'instance est dérivé à partir d'un objet
      méthode de classe, l'instance de classe stockée dans "__self__"
      est en fait la classe elle-même. Ainsi, appeler "x.f(1)" ou
      "C.f(1)" est équivalent à appeler "f(C, 1)" où "f" est la
      fonction sous-jacente.

      Notez que la transformation d'objet fonction en objet méthode
      d'instance se produit à chaque fois que l'attribut est récupéré
      à partir de l'instance. Dans certains cas, assigner l'attribut à
      une variable locale et appeler cette variable locale constitue
      une bonne optimisation. Notez aussi que cette transformation n'a
      lieu que pour les fonctions définies par l'utilisateur : les
      autres objets appelables (et les objets non appelables) sont
      récupérés sans transformation. Il est aussi important de noter
      que les fonctions définies par l'utilisateur qui sont attributs
      d'une instance de classe ne sont pas converties en méthodes
      liées ; ceci n'a lieu que pour les fonctions qui sont attributs
      de la classe.

   Fonctions générateurs
      Une fonction ou une méthode qui utilise l'instruction "yield"
      (voir la section L'instruction yield) est appelée *fonction
      générateur*. Une telle fonction, lorsqu'elle est appelée,
      retourne toujours un objet itérateur qui peut être utilisé pour
      exécuter le corps de la fonction : appeler la méthode
      "iterator.__next__()" de l'itérateur exécute la fonction jusqu'à
      ce qu'elle renvoie une valeur à l'aide de l'instruction "yield".
      Quand la fonction exécute l'instruction "return" ou se termine,
      une exception "StopIteration" est levée et l'itérateur a atteint
      la fin de l'ensemble de valeurs qu'il peut renvoyer.

   Fonctions coroutines
      Une fonction ou méthode définie en utilisant "async def" est
      appelée *fonction coroutine*. Une telle fonction, quand elle est
      appelée, renvoie un objet *coroutine*. Elle peut contenir des
      expressions "await" ou "async with" ou des instructions "async
      for". Voir également la section Objets coroutines.

   Fonctions générateurs asynchrones
      Une fonction ou une méthode définie avec "async def" et qui
      utilise l'instruction "yield" est appelée *fonction générateur
      asynchrone*. Une telle fonction, quand elle est appelée, renvoie
      un objet itérateur asynchrone qui peut être utilisé dans des
      instructions "async for" pour exécuter le corps de la fonction.

      Appeler la méthode "aiterator.__anext__" de l'itérateur
      asynchrone renvoie un *awaitable* qui, lorsqu'on l'attend,
      s'exécute jusqu'à ce qu'il fournisse une valeur à l'aide de
      l'expression "yield". Quand la fonction exécute une instruction
      "return" (sans valeur) ou arrive à la fin, une exception
      "StopAsyncIteration" est levée et l'itérateur asynchrone a
      atteint la fin de l'ensemble des valeurs qu'il peut produire.

   Fonctions natives
      Un objet fonction native est une enveloppe autour d'une fonction
      C. Nous pouvons citer "len()" et "math.sin()" ("math" est un
      module standard natif) comme fonctions natives. Le nombre et le
      type des arguments sont déterminés par la fonction C. Des
      attributs spéciaux en lecture seule existent : "__doc__"
      contient le texte de documentation de la fonction (ou "None"
      s'il n'y en a pas) ; "__name__" est le nom de la fonction ;
      "__self__" est défini à "None" ; "__module__" est le nom du
      module où la fonction est définie ou "None" s'il n'est pas
      disponible.

   Méthodes natives
      Ce sont des fonctions natives déguisées, contenant un objet
      passé à une fonction C en tant qu'argument supplémentaire
      implicite. Un exemple de méthode native est "une_liste.append()"
      ("une_liste" étant un objet liste). Dans ce cas, l'attribut
      spécial en lecture seule "__self__" est défini à l'objet
      *une_liste*.

   Classes
      Les classes sont des appelables. Ces objets sont normalement
      utilisés pour créer des instances d'elles-mêmes mais des
      variations sont possibles pour les types de classes qui
      surchargent "__new__()". Les arguments de l'appel sont passés à
      "__new__()" et, dans le cas classique, "__init__()" initialise
      une nouvelle instance.

   Instances de classe
      Les instances d'une classe peuvent devenir des appelables si
      vous définissez la méthode "__call__()" de leur classe.

Modules
   Les modules constituent l'organisation de base du code Python et
   sont créés par le mécanisme d'import soit avec l'instruction
   "import", soit en appelant des fonctions telles que
   "importlib.import_module()" ou la fonction native "__import__()".
   Un objet module possède un espace de nommage implémenté par un
   objet dictionnaire (c'est le dictionnaire référencé par l'attribut
   "__globals__" des fonctions définies dans le module). Les
   références à un attribut sont traduites en recherches dans ce
   dictionnaire, par exemple "m.x" est équivalent à "m.__dict__["x"]".
   Un objet module ne contient pas l'objet code utilisé pour
   initialiser le module (puisque celui-ci n'est plus nécessaire une
   fois l'initialisation terminée).

   L'assignation d'un attribut met à jour le dictionnaire d'espace de
   nommage du module, par exemple "m.x = 1" est équivalent à
   "m.__dict__["x"] = 1".

   Attributs prédéfinis (en lecture-écriture) : "__name__" est le nom
   du module ; "__doc__" est le texte de documentation du module (ou
   "None" s'il n'y en a pas) ; "__annotations__" (optionnel) est un
   dictionnaire contenant les *annotations de variables* collectées
   durant l'exécution du corps du module ; "__file__" est le chemin
   vers le fichier à partir duquel le module a été chargé, s'il a été
   chargé depuis un fichier. L'attribut "__file__" peut être manquant
   pour certains types de modules, tels que les modules C qui sont
   statiquement liés à l'interpréteur ; pour les modules d'extension
   chargés dynamiquement à partir d'une bibliothèque partagée, c'est
   le chemin vers le fichier de la bibliothèque partagée.

   Attribut spécial en lecture seule : "__dict__" est l'objet
   dictionnaire répertoriant l'espace de nommage du module.

   **CPython implementation detail:** en raison de la manière dont
   CPython nettoie les dictionnaires de modules, le dictionnaire du
   module est effacé quand le module n'est plus visible, même si le
   dictionnaire possède encore des références actives. Pour éviter
   ceci, copiez le dictionnaire ou gardez le module dans votre champ
   de visibilité tant que vous souhaitez utiliser le dictionnaire
   directement.

Classes déclarées par le développeur
   Le type d'une classe déclarée par le développeur est créé au moment
   de la définition de la classe (voir la section Définition de
   classes). Une classe possède un espace de nommage implémenté sous
   la forme d'un objet dictionnaire. Les références vers les attributs
   de la classe sont traduits en recherches dans ce dictionnaire, par
   exemple "C.x" est traduit en "C.__dict__["x"]" (bien qu'il existe
   un certain nombre de fonctions automatiques qui permettent de
   trouver des attributs par d'autres moyens). Si le nom d'attribut
   n'est pas trouvé dans ce dictionnaire, la recherche continue dans
   les classes de base. Les classes de base sont trouvées en utilisant
   l'ordre de résolution des méthodes (*method resolution order* en
   anglais, ou MRO) *C3* qui a un comportement cohérent même en
   présence d'héritages en "diamant", où différentes branches
   d'héritages conduisent vers un ancêtre commun. Vous trouverez plus
   de détails sur l'ordre de résolution des méthodes MRO *C3* utilisé
   par Python dans la documentation de la version 2.3 disponible sur
   https://www.python.org/download/releases/2.3/mro/.

   Quand une référence à un attribut de classe (disons la classe "C")
   pointe vers un objet méthode de classe, elle est transformée en
   objet méthode d'instance dont l'attribut "__self__" est "C". Quand
   elle pointe vers un objet méthode statique, elle est transformée en
   objet encapsulé par l'objet méthode statique. Reportez-vous à la
   section Implémentation de descripteurs pour une autre manière dont
   les attributs d'une classe diffèrent de ceux réellement contenus
   dans son "__dict__".

   Les assignations d'un attribut de classe mettent à jour le
   dictionnaire de la classe, jamais le dictionnaire d'une classe de
   base.

   Un objet classe peut être appelé (voir ci-dessus) pour produire une
   instance de classe (voir ci-dessous).

   Attributs spéciaux : "__name__" est le nom de la classe ;
   "__module__" est le nom du module dans lequel la classe est définie
   ; "__dict__" est le dictionnaire contenant l'espace de nommage de
   la classe ; "__bases__" est un *n*-uplet contenant les classes de
   base, dans l'ordre d'apparition dans la liste des classes de base ;
   "__doc__" est le texte de documentation de la classe (ou "None"
   s’il n’y en a pas) ; "__annotations__" (optionnel) est un
   dictionnaire contenant les *annotations de variables* collectées
   durant l'exécution du corps de la classe.

Instances de classe
   Une instance de classe est créée en appelant un objet classe (voir
   ci-dessus). Une instance de classe possède un espace de nommage
   implémenté sous la forme d'un dictionnaire qui est le premier
   endroit où sont recherchées les références aux attributs. Quand un
   attribut n'est pas trouvé dans ce dictionnaire et que la classe de
   l'instance contient un attribut avec ce nom, la recherche continue
   avec les attributs de la classe. Si un attribut de classe est
   trouvé et que c'est un objet fonction définie par l'utilisateur, il
   est transformé en objet méthode d'instance dont l'attribut
   "__self__" est l'instance. Les objets méthodes statiques et
   méthodes de classe sont aussi transformés ; reportez-vous ci-
   dessous à « Classes ». Lisez la section Implémentation de
   descripteurs pour une autre façon de récupérer les attributs d'une
   classe, où la récupération *via* ses instances peut différer des
   objets réellement stockés dans le "__dict__" de la classe. Si aucun
   attribut de classe n'est trouvé et que la classe de l'objet possède
   une méthode "__getattr__()", cette méthode est appelée pour
   rechercher une correspondance.

   Les affectations et suppressions d'attributs mettent à jour le
   dictionnaire de l'instance, jamais le dictionnaire de la classe. Si
   la classe possède une méthode "__setattr__()" ou "__delattr__()",
   elle est appelée au lieu de mettre à jour le dictionnaire de
   l'instance directement.

   Les instances de classes peuvent prétendre être des nombres, des
   séquences ou des tableaux de correspondance si elles ont des
   méthodes avec des noms spéciaux. Voir la section Méthodes
   spéciales.

   Attributs spéciaux : "__dict__" est le dictionnaire des attributs ;
   "__class__" est la classe de l'instance.

Objets Entrées-Sorties (ou objets fichiers)
   Un *objet fichier* représente un fichier ouvert. Différents
   raccourcis existent pour créer des objets fichiers : la fonction
   native "open()" et aussi "os.popen()", "os.fdopen()" ou la méthode
   "makefile()" des objets connecteurs (et sûrement d'autres fonctions
   ou méthodes fournies par les modules d'extensions).

   Les objets "sys.stdin", "sys.stdout" et "sys.stderr" sont
   initialisés à des objets fichiers correspondant à l'entrée
   standard, la sortie standard et le flux d'erreurs de l'interpréteur
   ; ils sont tous ouverts en mode texte et se conforment donc à
   l'interface définie par la classe abstraite "io.TextIOBase".

Types internes
   Quelques types utilisés en interne par l'interpréteur sont
   accessibles à l'utilisateur. Leur définition peut changer dans les
   futures versions de l'interpréteur mais ils sont donnés ci-dessous
   à fin d'exhaustivité.

   Objets Code
      Un objet code représente le code Python sous sa forme compilée
      en *bytecode*. La différence entre un objet code et un objet
      fonction est que l'objet fonction contient une référence
      explicite vers les globales de la fonction (le module dans
      lequel elle est définie) alors qu'un objet code ne contient
      aucun contexte ; par ailleurs, les valeurs par défaut des
      arguments sont stockées dans l'objet fonction, pas dans l'objet
      code (parce que ce sont des valeurs calculées au moment de
      l'exécution). Contrairement aux objets fonctions, les objets
      codes sont immuables et ne contiennent aucune référence (directe
      ou indirecte) à des objets muables.

      Attributs spéciaux en lecture seule : "co_name" donne le nom de
      la fonction ; "co_argcount" est le nombre total d'arguments
      positionnels (y compris les arguments uniquement positionnels et
      les arguments avec des valeurs par défaut) ;
      "co_posonlyargcount" est le nombre d'arguments uniquement
      positionnels (y compris les arguments avec des valeurs par
      défaut) ; "co_kwonlyargcount" est le nombre d'arguments par
      mots-clés (y compris les arguments avec des valeurs par défaut)
      ; "co_nlocals" est le nombre de variables locales utilisées par
      la fonction (y compris les arguments) ; "co_varnames" est un
      *n*-uplet contenant les noms des variables locales (en
      commençant par les noms des arguments) ; "co_cellvars" est un
      *n*-uplet contenant les noms des variables locales qui sont
      référencées par des fonctions imbriquées ; "co_freevars" est un
      *n*-uplet contenant les noms des variables libres ; "co_code"
      est une chaîne représentant la séquence des instructions de code
      intermédiaire ; "co_consts" est un *n*-uplet contenant les
      littéraux utilisés par le code intermédiaire ; "co_names" est un
      *n*-uplet contenant les noms utilisés par le code intermédiaire
      ; "co_filename" est le nom de fichier à partir duquel le code a
      été compilé ; "co_firstlineno" est numéro de la première ligne
      de la fonction ; "co_lnotab" est une chaîne codant la
      correspondance entre les décalages du code intermédiaire et les
      numéros de ligne (pour plus de détails, voir le code source de
      l'interpréteur) ; "co_stacksize" est la taille de pile requise ;
      "co_flags" est un entier qui code différents drapeaux pour
      l'interpréteur.

      Les drapeaux suivants sont codés par des bits dans "co_flags" :
      le bit "0x04" est positionné à 1 si la fonction utilise la
      syntaxe "*arguments" pour accepter un nombre arbitraire
      d'arguments positionnels ; le bit "0x08" est positionné à 1 si
      la fonction utilise la syntaxe "**keywords" pour accepter un
      nombre arbitraire d'arguments nommés ; le bit "0x20" est
      positionné à 1 si la fonction est un générateur.

      Les déclarations de fonctionnalité future "from __future__
      import division" utilisent aussi des bits dans "co_flags" pour
      indiquer si l'objet code a été compilé avec une fonctionnalité
      future : le bit "0x2000" est positionné à 1 si la fonction a été
      compilée avec la division future activée ; les bits "0x10" et
      "0x1000" étaient utilisés dans les versions antérieures de
      Python.

      Les autres bits de "co_flags" sont réservés à un usage interne.

      Si l'objet code représente une fonction, le premier élément dans
      "co_consts" est le texte de documentation de la fonction (ou
      "None" s'il n'y en a pas).

   Objets cadres
      Un objet cadre représente le cadre d'exécution. Il apparait dans
      des objets traces (voir plus loin) et est passé comme argument
      aux fonctions de traçage actives.

      Attributs spéciaux en lecture seule : "f_back" pointe vers le
      cadre précédent (l'appelant) ou "None" si c'est le pied de la
      pile d'appel ; "f_code" est l'objet code en cours d'exécution
      dans ce cadre ; "f_locals" est le dictionnaire dans lequel sont
      cherchées les variables locales ; "f_globals" est utilisé pour
      les variables globales ; "f_builtins" est utilisé pour les noms
      natifs ; "f_lasti" donne l'instruction précise (c'est un indice
      dans la chaîne de *bytecode* de l'objet code).

      La lecture de "f_code" lève un événement d'audit
      "object.__getattr__" avec les arguments "obj" et ""f_code"".

      Attributs spéciaux en lecture-écriture : "f_trace", s'il n'est
      pas "None", c'est une fonction appelée à différentes occasions
      durant l'exécution du code (elle est utilisée par le débogueur).
      Normalement, un événement est déclenché pour chaque ligne de
      code source — ce comportement peut être désactivé en définissant
      "f_trace_lines" à "False".

      Une implémentation *peut* autoriser le déclenchement des
      événements *opcode* par *opcode* en définissant
      "f_trace_opcodes" à "True". Notez que cela peut conduire à un
      comportement erratique de l'interpréteur si des exceptions
      levées la fonction de traçage s'échappent vers la fonction en
      train d'être tracée.

      "f_lineno" est le numéro de la ligne courante du cadre — écrire
      dedans depuis une fonction trace fait sauter à la ligne demandée
      (seulement pour le cadre le plus bas). Un débogueur peut
      implémenter une commande « sauter vers » (aussi appelée «
      Définir la prochaine instruction » ou *Set Next Statement* en
      anglais) en écrivant dans "f_lineno".

      Les objets cadres comprennent une méthode :

      frame.clear()

         Cette méthode efface toutes les références aux variables
         locales conservées dans le cadre. Par ailleurs, si le cadre
         est celui d'un générateur, le générateur se termine. Ceci
         permet de casser des références cycliques qui incluent des
         objets cadres (par exemple, lors de la capture d'une
         exception et du stockage de la pile d'appels pour une
         utilisation future).

         "RuntimeError" est levée si le cadre est en cours
         d'exécution.

         Nouveau dans la version 3.4.

   Objets traces
      Les objets *traces d'appels* représentent le contenu de la pile
      des appels au moment de l'exception. Un objet *trace d'appels*
      est implicitement créé quand une exception apparaît et peut être
      explicitement créé en appelant "types.TracebackType".

      Pour les traces créées implicitement, quand l'interpréteur
      recherche un gestionnaire d'exception en remontant la pile
      d'exécution, un objet trace est inséré devant l'objet trace
      courant à chaque nouveau niveau. Quand il entre dans le
      gestionnaire d'exception, la pile d'appels est rendue accessible
      au programme (voir la section L'instruction try). Elle est
      accessible par le troisième élément du triplet renvoyé par
      "sys.exc_info()" et comme attribut "__traceback__" de
      l'exception qui est traitée.

      Quand le programme ne contient aucun gestionnaire adéquat, la
      pile de traces est écrite (joliment formatée) sur la sortie
      d'erreur standard ; si l'interpréteur est interactif, elle est
      rendue disponible pour l'utilisateur en tant que
      "sys.last_traceback".

      Pour les traces créées explicitement, il revient au créateur de
      la trace de déterminer comment les attributs "tb_next" doivent
      être liés pour former la pile complète des traces.

      Attributs spéciaux en lecture seule : "tb_frame" pointe vers le
      cadre d'exécution du niveau courant ; "tb_lineno" donne le
      numéro de ligne où l'exception a été levée ; "tb_lasti" indique
      l'instruction précise. Le numéro de ligne et la dernière
      instruction dans la trace peuvent différer du numéro de ligne de
      l'objet cadre si l'exception a eu lieu dans une instruction
      "try" sans qu'il n'y ait de clause "except" adéquate ou sans
      clause *finally*.

      La lecture de "tb_frame" lève un événement d'audit
      "object.__getattr__" avec les arguments "obj" et ""tb_frame"".

      Attributs spéciaux en lecture-écriture "tb_next" est le niveau
      suivant dans la pile d'exécution (en direction du cadre où
      l'exception a eu lieu) ou "None" s'il n'y a pas de niveau
      suivant.

      Modifié dans la version 3.7: Les objets de traces d'appels
      peuvent maintenant être explicitement instanciés depuis le code
      Python et l'attribut "tb_next" des instances existantes peut
      être mis à jour.

   Objets tranches
      Un objet tranche est utilisé pour représenter des découpes des
      méthodes "__getitem__()". Ils sont aussi créés par la fonction
      native "slice()".

      Attributs spéciaux en lecture seule : "start" est la borne
      inférieure ; "stop" est la borne supérieure ; "step" est la
      valeur du pas ; chaque attribut vaut "None" s'il est omis. Ces
      attributs peuvent être de n'importe quel type.

      Les objets tranches comprennent une méthode :

      slice.indices(self, length)

         Cette méthode prend un argument entier *length* et calcule
         les informations de la tranche que l'objet découpe décrit
         s'il est appliqué à une séquence de *length* éléments. Elle
         renvoie un triplet d'entiers ; respectivement, ce sont les
         indices de *début* et *fin* ainsi que le *pas* de découpe.
         Les indices manquants ou en dehors sont gérés de manière
         cohérente avec les tranches normales.

   Objets méthodes statiques
      Les objets méthodes statiques permettent la transformation des
      objets fonctions en objets méthodes décrits au-dessus. Un objet
      méthode statique encapsule tout autre objet, souvent un objet
      méthode définie par l'utilisateur. Quand un objet méthode
      statique est récupéré depuis une classe ou une instance de
      classe, l'objet réellement renvoyé est un objet encapsulé, qui
      n'a pas vocation à être transformé encore une fois. Les objets
      méthodes statiques ne sont pas appelables en tant que tels, bien
      que les objets qu'ils encapsulent le soient souvent. Les objets
      méthodes statiques sont créés par le constructeur natif
      "staticmethod()".

   Objets méthodes de classes
      Un objet méthode de classe, comme un objet méthode statique,
      encapsule un autre objet afin de modifier la façon dont cet
      objet est récupéré depuis les classes et instances de classes.
      Le comportement des objets méthodes de classes dans le cas d'une
      telle récupération est décrit plus haut, dans « méthodes
      définies par l'utilisateur ». Les objets méthodes de classes
      sont créés par le constructeur natif "classmethod()".


3.3. Méthodes spéciales
=======================

Une classe peut implémenter certaines opérations que l'on invoque par
une syntaxe spéciale (telles que les opérations arithmétiques ou la
découpe en tranches) en définissant des méthodes aux noms
particuliers. C'est l'approche utilisée par Python pour la *surcharge
d'opérateur*, permettant à une classe de définir son propre
comportement vis-à-vis des opérateurs du langage. Par exemple, si une
classe définit une méthode "__getitem__()" et que "x" est une instance
de cette classe, alors "x[i]" est globalement équivalent à
"type(x).__getitem__(x, i)". Sauf lorsque c'est mentionné, toute
tentative d'appliquer une opération alors que la méthode appropriée
n'est pas définie lève une exception (typiquement "AttributeError" ou
"TypeError").

Définir une méthode spéciale à "None" indique que l'opération
correspondante n'est pas disponible. Par exemple, si une classe
assigne "None" à "__iter__()", vous ne pouvez pas itérer sur la classe
et appeler "iter()" sur une instance lève "TypeError" (sans se replier
sur "__getitem__()") [2].

Lorsque vous implémentez une classe qui émule un type natif, il est
important que cette émulation n'implémente que ce qui fait sens pour
l'objet qui est modélisé. Par exemple, la recherche d'éléments
individuels d'une séquence peut faire sens, mais pas l'extraction
d'une tranche (un exemple est l'interface de "NodeList" dans le modèle
objet des documents W3C).


3.3.1. Personnalisation de base
-------------------------------

object.__new__(cls[, ...])

   Appelée pour créer une nouvelle instance de la classe *cls*. La
   méthode "__new__()" est statique (c'est un cas particulier, vous
   n'avez pas besoin de la déclarer comme telle) qui prend comme
   premier argument la classe pour laquelle on veut créer une
   instance. Les autres arguments sont ceux passés à l'expression de
   l'objet constructeur (l'appel à la classe). La valeur de retour de
   "__new__()" doit être l'instance du nouvel objet (classiquement une
   instance de *cls*).

   Une implémentation typique crée une nouvelle instance de la classe
   en invoquant la méthode "__new__()" de la superclasse à l'aide de
   "super().__new__(cls[, …])" avec les arguments adéquats, puis
   modifie l'instance nouvellement créée en tant que de besoin avant
   de la renvoyer.

   Si "__new__()" est appelée pendant la construction de l'objet et
   renvoie une instance de *cls*, alors la méthode "__init__()" de la
   nouvelle instance est invoquée avec "__init__(self[, …])" où *self*
   est la nouvelle instance et les autres arguments sont les mêmes que
   ceux passés au constructeur de l'objet.

   Si "__new__()" ne renvoie pas une instance de *cls*, alors la
   méthode "__init__()" de la nouvelle instance n'est pas invoquée.

   L'objectif de "__new__()" est principalement, pour les sous-classes
   de types immuables (comme "int", "str" ou "tuple"), d'autoriser la
   création sur mesure des instances. Elle est aussi souvent
   surchargée dans les métaclasses pour particulariser la création des
   classes.

object.__init__(self[, ...])

   Appelée après la création de l'instance (par "__new__()"), mais
   avant le retour vers l'appelant. Les arguments sont ceux passés à
   l'expression du constructeur de classe. Si une classe de base
   possède une méthode "__init__()", la méthode "__init__()" de la
   classe dérivée, si elle existe, doit explicitement appeler cette
   méthode pour assurer une initialisation correcte de la partie
   classe de base de l'instance ; par exemple :
   "super().__init__([args…])".

   Comme "__new__()" et "__init__()" travaillent ensemble pour créer
   des objets ("__new__()" pour le créer, "__init__()" pour le
   particulariser), "__init__()" ne doit pas renvoyer de valeur "None"
   ; sinon une exception "TypeError" est levée à l'exécution.

object.__del__(self)

   Appelée au moment où une instance est sur le point d'être détruite.
   On l'appelle aussi finaliseur ou (improprement) destructeur. Si une
   classe de base possède une méthode "__del__()", la méthode
   "__del__()" de la classe dérivée, si elle existe, doit
   explicitement l'appeler pour s'assurer de l'effacement correct de
   la partie classe de base de l'instance.

   Il est possible (mais pas recommandé) que la méthode "__del__()"
   retarde la destruction de l'instance en créant une nouvelle
   référence vers cet objet. Python appelle ceci la *résurrection*
   d'objet. En fonction de l'implémentation, "__del__()" peut être
   appelée une deuxième fois au moment où l'objet ressuscité va être
   détruit ; l'implémentation actuelle de *CPython* ne l'appelle
   qu'une fois.

   Il n'est pas garanti que soient appelées les méthodes "__del__()"
   des objets qui existent toujours quand l'interpréteur termine.

   Note:

     "del x" n'appelle pas directement "x.__del__()" — la première
     décrémente le compteur de références de "x". La seconde n'est
     appelée que quand le compteur de références de "x" atteint zéro.

   **CPython implementation detail:** It is possible for a reference
   cycle to prevent the reference count of an object from going to
   zero.  In this case, the cycle will be later detected and deleted
   by the *cyclic garbage collector*.  A common cause of reference
   cycles is when an exception has been caught in a local variable.
   The frame's locals then reference the exception, which references
   its own traceback, which references the locals of all frames caught
   in the traceback.

   Voir aussi: Documentation du module "gc".

   Avertissement:

     En raison des conditions particulières qui règnent quand
     "__del__()" est appelée, les exceptions levées pendant son
     exécution sont ignorées et, à la place, un avertissement est
     affiché sur "sys.stderr". En particulier :

     * "__del__()" peut être invoquée quand du code arbitraire est en
       cours d'exécution, et ce dans n'importe quel fil d'exécution.
       Si "__del__()" a besoin de poser un verrou ou d'accéder à tout
       autre ressource bloquante, elle peut provoquer un blocage
       mutuel (*deadlock* en anglais) car la ressource peut être déjà
       utilisée par le code qui est interrompu pour exécuter la
       méthode "__del__()".

     * "__del__()" peut être exécutée pendant que l'interpréteur se
       ferme. En conséquence, les variables globales auxquelles elle
       souhaite accéder (y compris les autres modules) peuvent déjà
       être détruites ou assignées à "None". Python garantit que les
       variables globales dont le nom commence par un tiret bas sont
       supprimées de leur module avant que les autres variables
       globales ne le soient ; si aucune autre référence vers ces
       variables globales n'existe, cela peut aider à s'assurer que
       les modules importés soient toujours accessibles au moment où
       la méthode "__del__()" est appelée.

object.__repr__(self)

   Appelée par la fonction native "repr()" pour calculer la
   représentation « officielle » en chaîne de caractères d'un objet.
   Tout est fait pour que celle-ci ressemble à une expression Python
   valide pouvant être utilisée pour recréer un objet avec la même
   valeur (dans un environnement donné). Si ce n'est pas possible, une
   chaîne de la forme "<…une description utile…>" est renvoyée. La
   valeur renvoyée doit être un objet chaîne de caractères. Si une
   classe définit "__repr__()" mais pas "__str__()", alors
   "__repr__()" est aussi utilisée quand une représentation «
   informelle » en chaîne de caractères est demandée pour une instance
   de cette classe.

   Cette fonction est principalement utilisée à fins de débogage, il
   est donc important que la représentation donne beaucoup
   d'informations et ne soit pas ambigüe.

object.__str__(self)

   Appelée par "str(objet)" ainsi que les fonctions natives "format()"
   et "print()" pour calculer une chaîne de caractères « informelle »
   ou joliment mise en forme de représentation de l'objet. La valeur
   renvoyée doit être un objet string.

   Cette méthode diffère de "object.__repr__()" car il n'est pas
   attendu que "__str__()" renvoie une expression Python valide : une
   représentation plus agréable à lire ou plus concise peut être
   utilisée.

   C'est l'implémentation par défaut des appels à "object.__repr__()"
   du type natif "object".

object.__bytes__(self)

   Appelée par bytes pour calculer une représentation en chaîne
   *bytes* d'un objet. Elle doit renvoyer un objet "bytes".

object.__format__(self, format_spec)

   Appelée par la fonction native "format()" et, par extension, lors
   de l'évaluation de formatted string literals et la méthode
   "str.format()". Elle produit une chaîne de caractères « formatée »
   représentant un objet. L'argument "format_spec" est une chaîne de
   caractères contenant la description des options de formatage
   voulues. L'interprétation de l'argument "format_spec" est laissée
   au type implémentant "__format__()". Cependant, la plupart des
   classes délèguent le formatage aux types natifs ou utilisent une
   syntaxe similaire d'options de formatage.

   Lisez Mini-langage de spécification de format pour une description
   de la syntaxe standard du formatage.

   La valeur renvoyée doit être un objet chaîne de caractères.

   Modifié dans la version 3.4: La méthode "__format__" de "object"
   lui-même lève une "TypeError" si vous lui passez une chaîne non
   vide.

   Modifié dans la version 3.7: "object.__format__(x, '')" est
   maintenant équivalent à "str(x)" plutôt qu'à "format(str(x), '')".

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

   Ce sont les méthodes dites de « comparaisons riches ». La
   correspondance entre les symboles opérateurs et les noms de
   méthodes est la suivante : "x<y" appelle "x.__lt__(y)", "x<=y"
   appelle "x.__le__(y)", "x==y" appelle "x.__eq__(y)", "x!=y" appelle
   "x.__ne__(y)", "x>y" appelle "x.__gt__(y)" et "x>=y" appelle
   "x.__ge__(y)".

   Une méthode de comparaison riche peut renvoyer le singleton
   "NotImplemented" si elle n'implémente pas l'opération pour une
   paire donnée d'arguments. Par convention, "False" et "True" sont
   renvoyées pour une comparaison qui a réussi. Cependant, ces
   méthodes peuvent renvoyer n'importe quelle valeur donc, si
   l'opérateur de comparaison est utilisé dans un contexte booléen
   (par exemple dans une condition d'une instruction "if"), Python
   appelle "bool()" sur la valeur pour déterminer si le résultat est
   faux ou vrai.

   Par défaut, "object" implémente "__eq__()" en utilisant "is" et
   renvoie "NotImplemented" si la comparaison renvoie "False" : "True
   if x is y else NotImplemented". Pour "__ne__()", il délègue à
   "__eq__()" et renvoie le résultat inverse, sauf si c'est
   "NotImplemented". Il n'y a pas d'autres relations implicites pour
   les opérateurs de comparaison ou d'implémentations par défaut ; par
   exemple, "(x<y or x==y)" n'implique pas "x<=y". Pour obtenir une
   relation d'ordre total automatique à partir d'une seule opération,
   reportez-vous à "functools.total_ordering()".

   Lisez le paragraphe "__hash__()" pour connaître certaines notions
   importantes relatives à la création d'objets *hashable* qui
   acceptent les opérations de comparaison personnalisées et qui sont
   utilisables en tant que clés de dictionnaires.

   Il n'y a pas de versions avec les arguments interchangés de ces
   méthodes (qui seraient utilisées quand l'argument de gauche ne
   connaît pas l'opération alors que l'argument de droite la connaît)
   ; en lieu et place, "__lt__()" et "__gt__()" sont la réflexion
   l'une de l'autre, "__le__()" et "__ge__()" sont la réflexion l'une
   de l'autre et "__eq__()" ainsi que "__ne__()" sont réflexives. Si
   les opérandes sont de types différents et que l'opérande de droite
   est d'un type qui une sous-classe directe ou indirecte du type de
   l'opérande de gauche, alors la méthode symétrique de l'opérande de
   droite est prioritaire, sinon c'est la méthode de l'opérande de
   gauche qui est prioritaire. Les sous-classes virtuelles ne sont pas
   prises en compte.

object.__hash__(self)

   Appelée par la fonction native "hash()" et par les opérations sur
   les membres de collections hachées (ce qui comprend "set",
   "frozenset" et "dict"). La méthode "__hash__()" doit renvoyer un
   entier. La seule propriété requise est que les objets qui sont
   égaux pour la comparaison doivent avoir la même valeur de hachage ;
   il est conseillé de mélanger les valeurs de hachage des composants
   d'un objet qui jouent un rôle dans la comparaison des objets, en
   les emballant dans un *n*-uplet dont on calcule l'empreinte. Par
   exemple :

      def __hash__(self):
          return hash((self.name, self.nick, self.color))

   Note:

     "hash()" limite la valeur renvoyée d'un objet ayant une méthode
     "__hash__()" personnalisée à la taille d'un "Py_ssize_t". C'est
     classiquement 8 octets pour une implémentation 64 bits et 4
     octets sur une implémentation 32 bits. Si la méthode "__hash__()"
     d'un objet doit être interopérable sur des plateformes ayant des
     implémentations différentes, assurez-vous de vérifier la taille
     du hachage sur toutes les plateformes. Une manière facile de le
     faire est la suivante : "python -c "import sys;
     print(sys.hash_info.width)"".

   Si une classe ne définit pas de méthode "__eq__()", elle ne doit
   pas définir l'opération "__hash__()" non plus ; si elle définit
   "__eq__()" mais pas "__hash__()", les instances ne peuvent pas être
   utilisées en tant qu'élément dans une collection de hachables. Si
   une classe définit des objets mutables et implémente la méthode
   "__eq__()", elle ne doit pas implémenter "__hash__()" puisque
   l'implémentation des collections hachables requiert que les clés
   soient des empreintes immuables (si l'empreinte d'un objet change,
   il ne sera plus trouvé correctement dans le stockage du
   dictionnaire).

   Les classes définies par l'utilisateur possèdent des méthodes
   "__eq__()" et "__hash__()" par défaut ; ces méthodes répondent que
   tous les objets sont différents (sauf avec eux-mêmes) et
   "x.__hash__()" renvoie une valeur telle que "x == y" implique à la
   fois "x is y" et "hash(x) == hash(y)".

   Une classe qui surcharge "__eq__()" et qui ne définit pas
   "__hash__()" a sa méthode "__hash__()" implicitement assignée à
   "None". Quand la méthode "__hash__()" d'une classe est "None", une
   instance de cette classe lève "TypeError" quand un programme essaie
   de demander son empreinte et elle est correctement identifiée comme
   *non hachable* quand on vérifie "isinstance(obj,
   collections.abc.Hashable)".

   Si une classe qui surcharge "__eq__()" a besoin de conserver
   l'implémentation de "__hash__()" de la classe parente, vous devez
   l'indiquer explicitement à l'interpréteur en définissant "__hash__
   = <ClasseParente>.__hash__".

   Si une classe ne surcharge pas "__eq__()" et veut supprimer le
   calcul des empreintes, elle doit inclure "__hash__ = None" dans la
   définition de la classe. Une classe qui définit sa propre méthode
   "__hash__()" qui lève explicitement "TypeError" serait
   incorrectement identifiée comme hachable par un appel à
   "isinstance(obj, collections.abc.Hashable)".

   Note:

     Par défaut, les valeurs renvoyées par "__hash__()" pour les
     chaînes et les *bytes* sont « salées » avec une valeur aléatoire
     non prévisible. Bien qu'une empreinte reste constante tout au
     long d'un processus Python, sa valeur n'est pas prévisible entre
     deux invocations de Python.This is intended to provide protection
     against a denial-of-service caused by carefully-chosen inputs
     that exploit the worst case performance of a dict insertion,
     O(n^2) complexity.  See
     http://www.ocert.org/advisories/ocert-2011-003.html for
     details.Modifier les empreintes obtenues par hachage modifie
     l'ordre d'itération sur les *sets*. Python n'a jamais donné de
     garantie sur cet ordre (d'ailleurs, l'ordre n'est pas le même
     entre les implémentations 32 et 64 bits).Voir aussi
     "PYTHONHASHSEED".

   Modifié dans la version 3.3: la randomisation des empreintes est
   activée par défaut.

object.__bool__(self)

   Appelée pour implémenter les tests booléens et l'opération native
   "bool()" ; elle doit renvoyer "False" ou "True". Quand cette
   méthode n'est pas définie, "__len__()" est appelée, si elle est
   définie, et l'objet est considéré vrai si le résultat est non nul.
   Si une classe ne définit ni "__len__()" ni "__bool__()", toutes ses
   instances sont considérées comme vraies.


3.3.2. Personnalisation de l'accès aux attributs
------------------------------------------------

Les méthodes suivantes peuvent être définies pour personnaliser
l'accès aux attributs (utilisation, assignation, suppression de
"x.name") pour les instances de classes.

object.__getattr__(self, name)

   Appelée lorsque l'accès par défaut à l'attribut échoue en levant
   "AttributeError" (soit "__getattribute__()" lève "AttributeError"
   car *name* n'est pas un attribut de l'instance ou un attribut dans
   l'arborescence de la classe de "self" ; ou "__get__()" de la
   propriété *name* lève "AttributeError"). Cette méthode doit
   retourner soit la valeur (calculée) de l'attribut, soit lever une
   exception "AttributeError".

   Notez que si l'attribut est trouvé par le mécanisme normal,
   "__getattr__()" n'est pas appelée (c'est une asymétrie voulue entre
   "__getattr__()" et "__setattr__()"). Ce comportement est adopté à
   la fois pour des raisons de performance et parce que, sinon,
   "__getattr__()" n'aurait aucun moyen d'accéder aux autres attributs
   de l'instance. Notez que, au moins pour ce qui concerne les
   variables d'instance, vous pouvez simuler un contrôle total en
   n'insérant aucune valeur dans le dictionnaire des attributs de
   l'instance (mais en les insérant dans un autre objet à la place).
   Lisez la partie relative à la méthode "__getattribute__()" ci-
   dessous pour obtenir un contrôle total effectif sur l'accès aux
   attributs.

object.__getattribute__(self, name)

   Appelée de manière inconditionnelle pour implémenter l'accès aux
   attributs des instances de la classe. Si la classe définit
   également "__getattr__()", cette dernière n'est pas appelée à moins
   que "__getattribute__()" ne l'appelle explicitement ou ne lève une
   exception "AttributeError". Cette méthode doit renvoyer la valeur
   (calculée) de l'attribut ou lever une exception "AttributeError".
   Afin d'éviter une récursion infinie sur cette méthode, son
   implémentation doit toujours appeler la méthode de la classe de
   base avec le même paramètre *name* pour accéder à n'importe quel
   attribut dont elle a besoin. Par exemple,
   "object.__getattribute__(self, name)".

   Note:

     Cette méthode peut être shuntée lorsque la recherche porte sur
     les méthodes spéciales en tant que résultat d'une invocation
     implicite *via* la syntaxe du langage ou les fonctions natives.
     Lisez Recherche des méthodes spéciales.

   Lève un événement d'audit "object.__getattr__" avec les arguments
   "obj" et "name".

object.__setattr__(self, name, value)

   Appelée lors d'une assignation d'attribut. Elle est appelée à la
   place du mécanisme normal (c'est-à-dire stocker la valeur dans le
   dictionnaire de l'instance). *name* est le nom de l'attribut,
   *value* est la valeur à assigner à cet attribut.

   Si "__setattr__()" veut assigner un attribut d'instance, elle doit
   appeler la méthode de la classe de base avec le même nom, par
   exemple "object.__setattr__(self, name, value)".

   Lève un événement d'audit "object.__setattr__" avec les arguments
   "obj", "name" et "value".

object.__delattr__(self, name)

   Comme "__setattr__()" mais pour supprimer un attribut au lieu de
   l'assigner. Elle ne doit être implémentée que si "del obj.name" a
   du sens pour cet objet.

   Lève un événement d'audit "object.__deltattr__" avec les arguments
   "obj" et "name".

object.__dir__(self)

   Appelée quand "dir()" est appelée sur l'objet. Elle doit renvoyer
   une séquence. "dir()" convertit la séquence renvoyée en liste et
   effectue le classement.


3.3.2.1. Personnalisation de l'accès aux attributs d'un module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Les noms spéciaux "__getattr__" et "__dir__" peuvent aussi être
personnalisés pour accéder aux attributs du module. La fonction
"__getattr__" au niveau du module doit accepter un argument qui est un
nom d'attribut et doit renvoyer la valeur calculée ou lever une
"AttributeError". Si un attribut n'est pas trouvé dans l'objet module
en utilisant la recherche normale, c'est-à-dire
"object.__getattribute__()", alors Python recherche "__getattr__" dans
le "__dict__" du module avant de lever une "AttributeError". S'il la
trouve, il l'appelle avec le nom de l'attribut et renvoie le résultat.

La fonction "__dir__" ne prend aucun argument et renvoie une séquence
de chaînes qui représente les noms accessibles du module. Si elle
existe, cette fonction surcharge la fonction de recherche standard
"dir()" du module.

Pour une personnalisation plus fine du comportement d'un module
(assignation des attributs, propriétés, etc.), vous pouvez assigner
l'attribut "__class__" d'un objet module à une sous-classe de
"types.ModuleType". Par exemple :

   import sys
   from types import ModuleType

   class VerboseModule(ModuleType):
       def __repr__(self):
           return f'Verbose {self.__name__}'

       def __setattr__(self, attr, value):
           print(f'Setting {attr}...')
           super().__setattr__(attr, value)

   sys.modules[__name__].__class__ = VerboseModule

Note:

  Définir "__getattr__" du module et "__class__" pour le module
  affecte uniquement les recherches qui utilisent la syntaxe d'accès
  aux attributs — accéder directement aux globales d'un module (soit
  par le code dans le module, soit *via* une référence au dictionnaire
  des variables globales du module) fonctionne toujours de la même
  façon.

Modifié dans la version 3.5: l'attribut "__class__" du module est
maintenant en lecture-écriture.

Nouveau dans la version 3.7: attributs "__getattr__" et "__dir__" du
module.

Voir aussi:

  **PEP 562** — "__getattr__" et "__dir__" pour un module
     Décrit les fonctions "__getattr__" et "__dir__" des modules.


3.3.2.2. Implémentation de descripteurs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Les méthodes qui suivent s'appliquent seulement quand une instance de
la classe (dite classe *descripteur*) contenant la méthode apparaît
dans une classe *propriétaire* (*owner* en anglais) ; la classe
descripteur doit figurer dans le dictionnaire de la classe
propriétaire ou dans le dictionnaire de la classe d'un des parents.
Dans les exemples ci-dessous, « l'attribut » fait référence à
l'attribut dont le nom est une clé du "__dict__" de la classe
propriétaire.

object.__get__(self, instance, owner=None)

   Appelée pour obtenir l'attribut de la classe propriétaire (accès à
   un attribut de classe) ou d'une instance de cette classe (accès à
   un attribut d'instance). L'argument optionnel *owner* est la classe
   propriétaire alors que *instance* est l'instance par laquelle on
   accède à l'attribut ou "None" lorsque l'on accède par la classe
   *owner*.

   Il convient que cette méthode renvoie la valeur calculée de
   l'attribut ou lève une exception "AttributeError".

   La **PEP 252** spécifie que "__get__()" soit un appelable avec un
   ou deux arguments. Les descripteurs natifs de Python suivent cette
   spécification ; cependant, il est probable que des outils tiers
   aient des descripteurs qui requièrent les deux arguments.
   L'implémentation de "__getattribute__()" de Python passe toujours
   les deux arguments, qu'ils soient requis ou non.

object.__set__(self, instance, value)

   Appelée pour définir l'attribut d'une instance *instance* de la
   classe propriétaire à la nouvelle valeur *value*.

   Notez que ajouter "__set__()" ou "__delete__()" modifie la nature
   du descripteur vers un « descripteur de donnée ». Reportez-vous à
   Invocation des descripteurs pour plus de détails.

object.__delete__(self, instance)

   Appelée pour supprimer l'attribut de l'instance *instance* de la
   classe propriétaire.

object.__set_name__(self, owner, name)

   Appelée au moment où la classe propriétaire *owner* est créée. La
   classe descripteur a été assignée à *name*.

   Note:

     "__set_name__()" n'est appelée implicitement que par le
     constructeur de "type", vous devez donc l'appeler explicitement
     avec les paramètres adéquats quand un descripteur est ajouté à
     une classe après sa création :

        class A:
           pass
        descr = custom_descriptor()
        A.attr = descr
        descr.__set_name__(A, 'attr')

     Consultez Création de l'objet classe pour davantage de détails.

   Nouveau dans la version 3.6.

L'attribut "__objclass__" est interprété par le module "inspect" comme
spécifiant la classe où cet objet a été défini (le définir
correctement peut vous aider dans l'introspection des classes
dynamiques à l'exécution). Pour les appelables, cela peut indiquer
qu'une instance d'un certain type (ou d'une certaine sous-classe) est
attendue ou requise comme premier argument positionnel (par exemple,
CPython définit cet attribut pour les méthodes non liées qui sont
implémentées en C).


3.3.2.3. Invocation des descripteurs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

En général, un descripteur est un attribut d'objet dont le
comportement est « lié » (*binding dehavior* en anglais), c'est-à-dire
que les accès aux attributs ont été surchargés par des méthodes
conformes au protocole des descripteurs : "__get__()", "__set__()" et
"__delete__()". Si l'une de ces méthodes est définie pour un objet, il
est réputé être un descripteur.

Le comportement par défaut pour la gestion d'un attribut est de
définir, obtenir et supprimer cet attribut du dictionnaire de l'objet.
Par exemple, pour "a.x" Python commence d'abord par rechercher
"a.__dict__['x']", puis "type(a).__dict__['x']" ; ensuite Python
continue en remontant les classes de base de "type(a)", en excluant
les métaclasses.

Cependant, si la valeur cherchée est un objet qui définit une des
méthodes de descripteur, alors Python modifie son comportement et
invoque la méthode du descripteur à la place. Le moment où cela
intervient dans la recherche citée ci-dessus dépend de l'endroit où a
été définie la méthode de descripteur et comment elle a été appelée.

Le point de départ pour une invocation de descripteur est la liaison
"a.x". La façon dont les arguments sont assemblés dépend de "a" :

Appel direct
   Le plus simple et le plus rare des appels est quand l'utilisateur
   code directement l'appel à la méthode du descripteur :
   "x.__get__(a)".

Liaison avec une instance
   Si elle est liée à un objet instance, "a.x" est transformé en
   l'appel suivant : "type(a).__dict__['x'].__get__(a, type(a))".

Liaison avec une classe
   Si elle est liée à une classe, "A.x" est transformé en l'appel
   suivant : "A.__dict__['x'].__get__(None, A)".

Liaison super
   If "a" is an instance of "super", then the binding "super(B,
   obj).m()" searches "obj.__class__.__mro__" for the base class "A"
   immediately following "B" and then invokes the descriptor with the
   call: "A.__dict__['m'].__get__(obj, obj.__class__)".

Pour des liaisons avec des instances, la priorité à l'invocation du
descripteur dépend des méthodes que le descripteur a définies. Un
descripteur peut définir n'importe quelle combinaison de "__get__()",
"__set__()" et "__delete__()". S'il ne définit pas "__get__()", alors
accéder à l'attribut renvoie l'objet descripteur lui-même sauf s'il
existe une valeur dans le dictionnaire de l'objet instance. Si le
descripteur définit "__set__()" ou "__delete__()", c'est un
descripteur de données ; s'il ne définit aucune méthode, c'est un
descripteur hors-données. Normalement, les descripteurs de données
définissent à la fois "__get__()" et "__set__()", alors que les
descripteurs hors-données définissent seulement la méthode
"__get__()". Les descripteurs de données qui définissent "__set__()"
et "__get__()" (ou "__delete__()") sont toujours prioritaires face à
une redéfinition du dictionnaire de l'instance. En revanche, les
descripteurs hors-données peuvent être shuntés par les instances.

Les méthodes Python (y compris celles décorées par "@staticmethod" et
"@classmethod") sont implémentées comme des descripteurs hors-données.
De la même manière, les instances peuvent redéfinir et surcharger les
méthodes. Ceci permet à chaque instance d'avoir un comportement qui
diffère des autres instances de la même classe.

La fonction "property()" est implémentée en tant que descripteur de
données. Ainsi, les instances ne peuvent pas surcharger le
comportement d'une propriété.


3.3.2.4. "__slots__"
~~~~~~~~~~~~~~~~~~~~

Les créneaux prédéfinis ("__slots__") vous permettent de déclarer des
membres d'une donnée (comme une propriété) et d'interdire la création
de "__dict__" ou de *__weakref__* (à moins qu'ils ne soient
explicitement déclarés dans le "__slots__" ou présent dans le parent).

L'espace gagné par rapport à l'utilisation d'un "__dict__" peut être
significatif. La recherche d'attribut peut aussi s'avérer beaucoup
plus rapide.

object.__slots__

   Cette variable de classe peut être assignée avec une chaîne, un
   itérable ou une séquence de chaînes avec les noms de variables
   utilisés par les instances. *__slots__* réserve de la place pour
   ces variables déclarées et interdit la création automatique de
   "__dict__" et *__weakref__* pour chaque instance.


3.3.2.4.1. Note sur l'utilisation de *__slots__*
""""""""""""""""""""""""""""""""""""""""""""""""

* Lorsque vous héritez d'une classe sans *__slots__*, les attributs
  "__dict__" et *__weakref__* des instances sont toujours accessibles.

* Sans variable "__dict__", les instances ne peuvent pas assigner de
  nouvelles variables (non listées dans la définition de *__slots__*).
  Les tentatives d'assignation sur un nom de variable non listé lève
  "AttributeError". Si l'assignation dynamique de nouvelles variables
  est nécessaire, ajoutez "'__dict__'" à la séquence de chaînes dans
  la déclaration *__slots__*.

* Sans variable *__weakref__* pour chaque instance, les classes qui
  définissent *__slots__* ne gèrent pas les "références faibles" vers
  leurs instances. Si vous avez besoin de gérer des références
  faibles, ajoutez "'__weakref__'" à la séquence de chaînes dans la
  déclaration de *__slots__*.

* Les *__slots__* sont implémentés au niveau de la classe en créant
  des descripteurs pour chaque nom de variable. Ainsi, les attributs
  de classe ne peuvent pas être utilisés pour des valeurs par défaut
  aux variables d'instances définies par *__slots__* ; sinon,
  l'attribut de classe surchargerait l'assignation par descripteur.

* L'action de la déclaration du *__slots__* ne se limite pas à la
  classe où il est défini. Les *__slots__* déclarés par les parents
  sont disponibles dans les classes enfants. Cependant, les sous-
  classes enfants ont un "__dict__" et un *__weakref__* à moins
  qu'elles ne définissent aussi un *__slots__* (qui ne doit contenir
  alors que les noms *supplémentaires* aux créneaux déjà prédéfinis).

* Si une classe définit un *slot* déjà défini dans une classe de base,
  la variable d'instance définie par la classe de base est
  inaccessible (sauf à utiliser le descripteur de la classe de base
  directement). Cela rend la signification du programme indéfinie.
  Dans le futur, une vérification sera ajoutée pour empêcher cela.

* Un *__slot__* non vide ne fonctionne pas pour les classes dérivées
  des types natifs à longueur variable tels que "int", "bytes" et
  "tuple".

* Tout *itérable*, sauf les chaînes de caractères, peuvent être
  affectés à *__slots__*.

* Si vous affectez *__slots__* à un "dictionnaire", les clés du
  dictionnaires seront les noms du *slot*. Les valeurs du dictionnaire
  peuvent être utilisées en tant que chaines de description
  (*docstrings*) et sont reconnues par "inspect.getdoc()" qui les
  affiche dans la sortie de "help()".

* Les assignations de "__class__" ne fonctionnent que si les deux
  classes ont le même *__slots__*.

* L'héritage multiple avec plusieurs classes parentes qui ont des
  *__slots__* est possible, mais seul un parent peut avoir des
  attributs créés par *__slots__* (les autres classes parentes doivent
  avoir des *__slots__* vides). La violation de cette règle lève
  "TypeError".

* Si un *itérateur* est utilisé pour *__slots__*, alors un
  *descripteur* est créé pour chacune des valeurs de l'itérateur.
  Cependant, l'attribut *__slots__* est un itérateur vide.


3.3.3. Personnalisation de la création de classes
-------------------------------------------------

Quand une classe hérite d'une classe parente, la méthode
"__init_subclass__()" de la classe parente est appelée. Ainsi, il est
possible d'écrire des classes qui modifient le comportement des sous-
classes. Ce comportement est corrélé aux décorateurs de classes mais,
alors que les décorateurs de classes agissent seulement sur la classe
qu'ils décorent, "__init_subclass__" agit uniquement sur les futures
sous-classes de la classe qui définit cette méthode.

classmethod object.__init_subclass__(cls)

   Cette méthode est appelée quand la classe est sous-classée. *cls*
   est alors la nouvelle sous-classe. Si elle est définie en tant que
   méthode d'instance normale, cette méthode est implicitement
   convertie en méthode de classe.

   Les arguments nommés qui sont donnés à la nouvelle classe sont
   passés à "__init_subclass__" de la classe parente. Par souci de
   compatibilité avec les autres classes qui utilisent
   "__init_subclass__", vous devez enlever les arguments nommés dont
   vous avez besoin et passer les autres à la classe de base, comme
   ci-dessous :

      class Philosopher:
          def __init_subclass__(cls, /, default_name, **kwargs):
              super().__init_subclass__(**kwargs)
              cls.default_name = default_name

      class AustralianPhilosopher(Philosopher, default_name="Bruce"):
          pass

   L'implémentation par défaut "object.__init_subclass__" ne fait rien
   mais lève une erreur si elle est appelée avec un argument.

   Note:

     L'indication de métaclasse "metaclass" est absorbée par le reste
     du mécanisme de types et n'est jamais passée à l'implémentation
     de "__init_subclass__". La métaclasse réelle (plutôt que
     l'indication explicite) peut être récupérée par "type(cls)".

   Nouveau dans la version 3.6.


3.3.3.1. Métaclasses
~~~~~~~~~~~~~~~~~~~~

Par défaut, les classes sont construites en utilisant "type()". Le
corps de la classe est exécuté dans un nouvel espace de nommage et le
nom de la classe est lié localement au résultat de *type(name, bases,
namespace)`*.

Le déroulement de création de la classe peut être personnalisé en
passant l'argument nommé "metaclass" dans la ligne de définition de la
classe ou en héritant d'une classe existante qui comporte déjà un tel
argument. Dans l'exemple qui suit, "MyClass" et "MySubclass" sont des
instances de "Meta" :

   class Meta(type):
       pass

   class MyClass(metaclass=Meta):
       pass

   class MySubclass(MyClass):
       pass

Tout autre argument nommé spécifié dans la définition de la classe est
passé aux opérations de métaclasses décrites auparavant.

Quand la définition d'une classe est exécutée, les différentes étapes
suivies sont :

* Les entrées MRO sont résolues ;

* la métaclasse appropriée est déterminée ;

* l'espace de nommage de la classe est préparé ;

* le corps de la classe est exécuté ;

* l'objet classe est crée.


3.3.3.2. Résolution des entrées MRO
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Si une classe de base qui apparaît dans la définition d'une classe
n'est pas une instance de "type", alors Python y recherche une méthode
"__mro_entries__". S'il la trouve, il l'appelle avec le *n*-uplet
original des classes de bases. Cette méthode doit renvoyer un
*n*-uplet de classes qui est utilisé à la place de la classe de base.
Le *n*-uplet peut être vide, dans ce cas la classe de base originale
est ignorée.

Voir aussi:

  **PEP 560** — Gestion de base pour les types modules et les types
  génériques


3.3.3.3. Détermination de la métaclasse appropriée
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

La métaclasse appropriée pour une définition de classe est déterminée
de la manière suivante :

* si aucune classe et aucune métaclasse n'est donnée, alors "type()"
  est utilisée ;

* si une métaclasse explicite est donnée et que *ce n'est pas* une
  instance de "type()", alors elle est utilisée directement en tant
  que métaclasse ;

* si une instance de "type()" est donnée comme métaclasse explicite ou
  si *bases* est définie, alors la métaclasse la plus dérivée est
  utilisée.

La métaclasse la plus dérivée est choisie à partir des métaclasses
explicitement spécifiées (s'il y en a) et les métaclasses
(c'est-à-dire les "type(cls)") de toutes les classes de base
spécifiées. La métaclasse la plus dérivée est celle qui est un sous-
type de *toutes* ces métaclasses candidates. Si aucune des métaclasses
candidates ne remplit ce critère, alors la définition de la classe
échoue en levant "TypeError".


3.3.3.4. Préparation de l'espace de nommage de la classe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Une fois que la métaclasse appropriée est identifiée, l'espace de
nommage de la classe est préparé. Si la métaclasse possède un attribut
"__prepare__", il est appelé avec "namespace =
metaclass.__prepare__(name, bases, **kwds)" (où les arguments nommés
supplémentaires, s'il y en a, sont les arguments de la définition de
la classe). La méthode "__prepare__" doit être implémentée comme une
"méthode de classe"). L’espace de nommage renvoyé par "__prepare__"
est passé à "__new__", mais quand l’instance finale est créée,
l’espace de nommage est copié vers un nouveau "dict".

Si la métaclasse ne possède pas d'attribut "__prepare__", alors
l'espace de nommage de la classe est initialisé en tant que tableau de
correspondances ordonné.

Voir aussi:

  **PEP 3115** — Métaclasses dans Python 3000
     introduction de la fonction automatique "__prepare__" de l'espace
     de nommage


3.3.3.5. Exécution du corps de la classe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Le corps de la classe est exécuté (approximativement) avec "exec(body,
globals(), namespace)". La principale différence avec un appel normal
à "exec()" est que la portée lexicale autorise le corps de la classe
(y compris les méthodes) à faire référence aux noms de la portée
courante et des portées externes lorsque la définition de classe a
lieu dans une fonction.

Cependant, même quand une définition de classe intervient dans une
fonction, les méthodes définies à l'intérieur de la classe ne peuvent
pas voir les noms définis en dehors de la portée de la classe. On
accède aux variables de la classe *via* le premier paramètre des
méthodes d'instance ou de classe, ou *via* la référence implicite
"__class__" incluse dans la portée lexicale et décrite dans la section
suivante.


3.3.3.6. Création de l'objet classe
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Quand l'espace de nommage a été rempli en exécutant le corps de la
classe, l'objet classe est créé en appelant "metaclass(name, bases,
namespace, **kwds)" (les arguments nommés supplémentaires passés ici
sont les mêmes que ceux passés à "__prepare__").

Cet objet classe est celui qui est référencé par la forme sans
argument de "super()". "__class__" est une référence implicite créée
par le compilateur si une méthode du corps de la classe fait référence
soit à "__class__", soit à "super". Ceci permet que la forme sans
argument de "super()" identifie la classe en cours de définition en
fonction de la portée lexicale, tandis que la classe ou l'instance
utilisée pour effectuer l'appel en cours est identifiée en fonction du
premier argument transmis à la méthode.

**CPython implementation detail:** Dans CPython 3.6 et suivants, la
cellule "__class__" est passée à la métaclasse en tant qu'entrée
"__classcell__" dans l'espace de nommage de la classe. Si elle est
présente, elle doit être propagée à l'appel "type.__new__" pour que la
classe soit correctement initialisée. Ne pas le faire se traduit par
un "RuntimeError" dans Python 3.8.

Quand vous utilisez la métaclasse par défaut "type" ou toute autre
métaclasse qui finit par appeler "type.__new__", les étapes de
personnalisation supplémentaires suivantes sont suivies après la
création de l'objet classe :

* d'abord, "type.__new__" récupère, dans l'espace de nommage de la
  classe, tous les descripteurs qui définissent une méthode
  "__set_name__()" ;

* ensuite, toutes ces méthodes "__set_name__" sont appelées avec la
  classe en cours de définition et le nom assigné à chaque descripteur
  ;

* finalement, la méthode automatique "__init_subclass__()" est appelée
  sur le parent immédiat de la nouvelle classe en utilisant l'ordre de
  résolution des méthodes.

Après la création de l'objet classe, il est passé aux décorateurs de
la classe, y compris ceux inclus dans la définition de la classe (s'il
y en a) et l'objet résultant est lié à l'espace de nommage local en
tant que classe définie.

Quand une nouvelle classe est créée *via* "type.__new__", l'objet
fourni en tant que paramètre d'espace de nommage est copié vers un
nouveau tableau de correspondances ordonné et l'objet original est
laissé de côté. La nouvelle copie est encapsulée dans un mandataire en
lecture seule qui devient l'attribut "__dict__" de l'objet classe.

Voir aussi:

  **PEP 3135** — Nouvelle méthode super
     Décrit la référence à la fermeture (*closure* en anglais) de la
     "__class__" implicite


3.3.3.7. Cas d'utilisations des métaclasses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Les utilisations possibles des métaclasses sont immenses. Quelques
pistes ont déjà été explorées comme l'énumération, la gestion des
traces, le contrôle des interfaces, la délégation automatique, la
création automatique de propriétés, les mandataires, les *frameworks*
ainsi que le verrouillage ou la synchronisation automatique de
ressources.


3.3.4. Personnalisation des instances et vérification des sous-classes
----------------------------------------------------------------------

Les méthodes suivantes sont utilisées pour surcharger le comportement
par défaut des fonctions natives "isinstance()" et "issubclass()".

En particulier, la métaclasse "abc.ABCMeta" implémente ces méthodes
pour autoriser l'ajout de classes de base abstraites (ABC pour
*Abstract Base Classes* en anglais) en tant que « classes de base
virtuelles » pour toute classe ou type (y compris les types natifs).

class.__instancecheck__(self, instance)

   Renvoie "True" si *instance* doit être considérée comme une
   instance (directe ou indirecte) de *class*. Si elle est définie,
   elle est appelée pour implémenter "isinstance(instance, class)".

class.__subclasscheck__(self, subclass)

   Renvoie "True" si *subclass* doit être considérée comme une sous-
   classe (directe ou indirecte) de *class*. Si elle est définie,
   appelée pour implémenter "issubclass(subclass, class)".

Notez que ces méthodes sont recherchées dans le type (la métaclasse)
d'une classe. Elles ne peuvent pas être définies en tant que méthodes
de classe dans la classe réelle. C'est cohérent avec la recherche des
méthodes spéciales qui sont appelées pour les instances, sauf qu'ici
l'instance est elle-même une classe.

Voir aussi:

  **PEP 3119** — Introduction aux classes de bases abstraites
     Inclut la spécification pour la personnalisation du comportement
     de "isinstance()" et "issubclass()" à travers
     "__instancecheck__()" et "__subclasscheck__()", avec comme
     motivation pour cette fonctionnalité l'ajout les classes de base
     abstraites (voir le module "abc") au langage.


3.3.5. Émulation de types génériques
------------------------------------

Lors de l'utilisation d'*annotations de types*, il est souvent utile
de *paramètrer* un *type générique* en se servant de la notation
crochets de Python. Par exemple, l'annotation "list[int]" peut être
utilisée pour signifier une "liste" dans laquelle tous les éléments
sont de type "entiers".

Voir aussi:

  **PEP 343** — Indications de types
     Introduction à l'annotation de types en Python (document en
     anglais)

  Types alias génériques
     Documentation pour les objets qui représentent des classes
     génériques paramétrées

  Génériques, Types génériques définis par l'utilisateur et classe
  "typing.Generic (classe de base abstraite pour les types
  génériques)"
     Documentation sur la manière d'implémenter des classes génériques
     qui peuvent être paramétrées à l'exécution et comprises par les
     vérificateurs statiques de types.

*Généralement*, une classe ne peut être paramétrée que si elle définit
une méthode spéciale de classe "__class_getitem__()".

classmethod object.__class_getitem__(cls, key)

   Renvoie un objet représentant la spécialisation d'une classe
   générique en fonction des arguments types trouvés dans *key*.

   Lorsqu'elle est définie dans une classe, "__class_getitem__()" est
   automatiquement une méthode de classe. Ainsi, il est superflu de la
   décorer avec "@classmethod" lors de sa définition.


3.3.5.1. Intention de *__class_getitem__*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Le but de "__class_getitem__()" est de permettre la paramétrisation à
l'exécution des classes génériques de la bibliothèque standard de
façon à pouvoir appliquer plus facilement des *annotations de type* à
ces classes.

Pour implémenter des classes génériques particularisées pouvant être
paramétrées à l'exécution, et comprises par les vérificateurs
statiques de type, vous pouvez soit hériter d'une classe de la
bibliothèque standard qui implémente déjà "__class_getitem__()", ou
hériter de "typing.Generic", qui a sa propre implémentation de
"__class_getitem__()".

Les implémentations particularisées de "__class_getitem__()" sur des
classes définies ailleurs que la bibliothèque standard peuvent ne pas
être comprises par des vérificateurs de types tiers tels que *mypy*.
L'utilisation de "__class_getitem__()" pour tout autre objectif que
l'annotation de type n'est pas conseillée.


3.3.5.2. *__class_getitem__* contre *__getitem__*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

D'habitude, l'indiçage d'un objet en utilisant des crochets appelle la
méthode "__getitem__()" de l'instance, définie dans la classe de
l'objet. Cependant, si l'objet dont on cherche un indice est lui-même
une classe, la méthode de classe "__class_getitem__()" peut être
appelée à la place. "__class_getitem__()" doit renvoyer un objet
GenericAlias si elle est correctement définie.

Lorsqu'on lui présente l'*expression* "obj[x]", l'interpréteur Python
suit une sorte de processus suivant pour décider s'il faut appeler
"__getitem__()" ou "__class_getitem__()" :

   from inspect import isclass

   def subscribe(obj, x):
       """Return the result of the expression `obj[x]`"""

       class_of_obj = type(obj)

       # If the class of obj defines __getitem__,
       # call class_of_obj.__getitem__(obj, x)
       if hasattr(class_of_obj, '__getitem__'):
           return class_of_obj.__getitem__(obj, x)

       # Else, if obj is a class and defines __class_getitem__,
       # call obj.__class_getitem__(x)
       elif isclass(obj) and hasattr(obj, '__class_getitem__'):
           return obj.__class_getitem__(x)

       # Else, raise an exception
       else:
           raise TypeError(
               f"'{class_of_obj.__name__}' object is not subscriptable"
           )

En Python, toutes les classes sont des instances d'autres classes. La
classe d'une classe est appelée la *métaclasse* de la classe et la
plupart des classes ont la classe "type" comme métaclasse. "type" ne
définit pas "__getitem__()", ce qui veut dire que des expressions
telles que "list[int]", "dict[str, float]" et "tuple[str, bytes]"
aboutissent toutes à l'appel de "__class_getitem__()" :

   >>> # list has class "type" as its metaclass, like most classes:
   >>> type(list)
   <class 'type'>
   >>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
   True
   >>> # "list[int]" calls "list.__class_getitem__(int)"
   >>> list[int]
   list[int]
   >>> # list.__class_getitem__ returns a GenericAlias object:
   >>> type(list[int])
   <class 'types.GenericAlias'>

Cependant, si une classe a une métaclasse particularisée qui définit
"__getitem__()", l'indiçage de la classe peut conduire à un
comportement différent. Un exemple peut être trouvé dans le module
"enum" :

   >>> from enum import Enum
   >>> class Menu(Enum):
   ...     """A breakfast menu"""
   ...     SPAM = 'spam'
   ...     BACON = 'bacon'
   ...
   >>> # Enum classes have a custom metaclass:
   >>> type(Menu)
   <class 'enum.EnumMeta'>
   >>> # EnumMeta defines __getitem__,
   >>> # so __class_getitem__ is not called,
   >>> # and the result is not a GenericAlias object:
   >>> Menu['SPAM']
   <Menu.SPAM: 'spam'>
   >>> type(Menu['SPAM'])
   <enum 'Menu'>

Voir aussi:

  **PEP 560** - Core Support for typing module and generic types
     Introduction de "__class_getitem__()", et présentation des cas où
     un indiçage conduit à l'appel de "__class_getitem__()" au lieu de
     "__getitem__()"


3.3.6. Émulation d'objets appelables
------------------------------------

object.__call__(self[, args...])

   Appelée quand l'instance est « appelée » en tant que fonction ; si
   la méthode est définie, "x(arg1, arg2, …)" est un raccourci pour
   "type(x).__call__(x, arg1, …)".


3.3.7. Émulation de types conteneurs
------------------------------------

Les fonctions suivantes peuvent être définies pour implémenter des
objets conteneurs. Les conteneurs sont habituellement des *séquences*
(telles que les "listes" ou les "n-uplets") ou des *tableaux de
correspondances* (comme les "dictionnaires"), mais ils peuvent aussi
représenter d'autres conteneurs. Le premier ensemble de méthodes est
utilisé soit pour émuler une séquence, soit pour émuler un tableau de
correspondances ; la différence est que, pour une séquence, les clés
doivent être soit des entiers *k* tels que "0 <= k < N" où *N* est la
longueur de la séquence, soit des objets "tranches" qui définissent un
intervalle d'éléments. Il est aussi recommandé que les tableaux de
correspondances fournissent les méthodes "keys()", "values()",
"items()", "get()", "clear()", "setdefault()", "pop()", "popitem()",
"copy()" et "update()" avec un comportement similaire aux objets
"dictionnaires" standards de Python. Le module "collections.abc"
fournit une *classe de base abstraite* "MutableMapping" pour aider à
la création de ces méthodes à partir d'un ensemble de base composé de
"__getitem__()", "__setitem__()", "__delitem__()" et "keys()". Les
séquences muables doivent fournir les méthodes "append()", "count()",
"index()", "extend()", "insert()", "pop()", "remove()", "reverse()" et
"sort()", comme les objets "listes" standards de Python. Enfin, les
types séquences doivent implémenter l'addition (dans le sens de la
concaténation) et la multiplication (dans le sens de la répétition) en
définissant les méthodes "__add__()", "__radd__()", "__iadd__()",
"__mul__()", "__rmul__()" et "__imul__()" décrites ci-dessous ; ils ne
doivent pas définir d'autres opérateurs numériques. Il est recommandé
que les tableaux de correspondances et les séquences implémentent la
méthode "__contains__()" pour permettre l'utilisation efficace de
l'opérateur "in" ; concernant les tableaux de correspondances, "in"
doit rechercher dans les clés du tableau ; pour les séquences, il doit
chercher dans les valeurs. Il est de plus recommandé que les tableaux
de correspondances et les séquences implémentent la méthode
"__iter__()" pour permettre une itération efficace dans le conteneur ;
pour les tableaux de correspondances, "__iter__()" doit itérer sur les
clés de l'objet ; pour les séquences, elle doit itérer sur les
valeurs.

object.__len__(self)

   Appelée pour implémenter la fonction native "len()". Elle doit
   renvoyer la longueur de l'objet, un entier ">=" 0. Par ailleurs, un
   objet qui ne définit pas de méthode "__bool__()" et dont la méthode
   "__len__()" renvoie zéro est considéré comme valant "False" dans un
   contexte booléen.

   **CPython implementation detail:** En CPython, la longueur doit
   valoir au maximum "sys.maxsize". Si la longueur est plus grande que
   "sys.maxsize", des propriétés (telles que "len()") peuvent lever
   "OverflowError". Afin d'éviter de lever "OverflowError" lors de
   tests booléens, un objet doit définir la méthode "__bool__()".

object.__length_hint__(self)

   Appelée pour implémenter "operator.length_hint()". Elle doit
   renvoyer une longueur estimée de l'objet (qui peut être plus grande
   ou plus petite que la longueur réelle). La longueur doit être un
   entier ">=" 0. La valeur de retour peut aussi être
   "NotImplemented", qui est traitée de la même façon que si la
   méthode "__length_hint__" n'existait pas. Cette méthode est
   utilisée uniquement pour optimiser les traitements et n'est jamais
   tenue de renvoyer un résultat exact.

   Nouveau dans la version 3.4.

Note:

  Le découpage est effectué uniquement à l'aide des trois méthodes
  suivantes. Un appel comme :

     a[1:2] = b

  est traduit en :

     a[slice(1, 2, None)] = b

  et ainsi de suite. Les éléments manquants sont remplacés par "None".

object.__getitem__(self, key)

   Appelée pour implémenter l'évaluation de "self[key]". Pour les
   types *séquences*, les clés autorisées sont les entiers et les
   objets tranches (*slice*). Notez que l'interprétation spéciale des
   indices négatifs (si la classe souhaite émuler un type *séquence*)
   est du ressort de la méthode "__getitem__()". Si *key* n'est pas du
   bon type, une "TypeError" peut être levée ; si la valeur est en
   dehors de l'ensemble des indices de la séquence (après
   interprétation éventuelle des valeurs négatives), une "IndexError"
   doit être levée. Pour les *tableaux de correspondances*, si *key*
   n'existe pas dans le conteneur, une "KeyError" doit être levée.

   Note:

     "for" s'attend à ce qu'une "IndexError" soit levée en cas
     d'indice illégal afin de détecter correctement la fin de la
     séquence.

   Note:

     quand on vous spécifiez un indice pour une *classe*, la méthode
     de classe spéciale "__class_getitem__()" peut être appelée au
     lieu de "__getitem__()". Reportez-vous à __class_getitem__ contre
     __getitem__ pour plus de détails.

object.__setitem__(self, key, value)

   Appelée pour implémenter l'assignation à "self[key]". La même note
   que pour "__getitem__()" s'applique. Elle ne doit être implémentée
   que pour les tableaux de correspondances qui autorisent les
   modifications de valeurs des clés, ceux pour lesquels on peut
   ajouter de nouvelles clés ou, pour les séquences, celles dont les
   éléments peuvent être remplacés. Les mêmes exceptions que pour la
   méthode "__getitem__()" doivent être levées en cas de mauvaises
   valeurs de clés.

object.__delitem__(self, key)

   Appelée pour implémenter la suppression de "self[key]". La même
   note que pour "__getitem__()" s'applique. Elle ne doit être
   implémentée que pour les tableaux de correspondances qui autorisent
   les suppressions de clés ou pour les séquences dont les éléments
   peuvent être supprimés de la séquence. Les mêmes exceptions que
   pour la méthode "__getitem__()" doivent être levées en cas de
   mauvaises valeurs de clés.

object.__missing__(self, key)

   Appelée par "dict"."__getitem__()" pour implémenter "self[key]"
   dans les sous-classes de dictionnaires lorsque la clé n'est pas
   dans le dictionnaire.

object.__iter__(self)

   Cette méthode est appelée quand un itérateur est requis pour un
   conteneur. Cette méthode doit renvoyer un nouvel objet itérateur
   qui peut itérer sur tous les objets du conteneur. Pour les tableaux
   de correspondances, elle doit itérer sur les clés du conteneur.

   Les objets itérateurs doivent aussi implémenter cette méthode ; ils
   doivent alors se renvoyer eux-mêmes. Pour plus d'information sur
   les objets itérateurs, lisez Les types itérateurs.

object.__reversed__(self)

   Appelée (si elle existe) par la fonction native "reversed()" pour
   implémenter l'itération en sens inverse. Elle doit renvoyer un
   nouvel objet itérateur qui itère sur tous les objets du conteneur
   en sens inverse.

   Si la méthode "__reversed__()" n'est pas fournie, la fonction
   native "reversed()" se replie sur le protocole de séquence
   ("__len__()" et "__getitem__()"). Les objets qui connaissent le
   protocole de séquence ne doivent fournir "__reversed__()" que si
   l'implémentation qu'ils proposent est plus efficace que celle de
   "reversed()".

Les opérateurs de tests d'appartenance ("in" et "not in") sont
normalement implémentés comme des itérations sur un conteneur.
Cependant, les objets conteneurs peuvent fournir les méthodes
spéciales suivantes avec une implémentation plus efficace, qui ne
requièrent d'ailleurs pas que l'objet soit itérable.

object.__contains__(self, item)

   Appelée pour implémenter les opérateurs de test d'appartenance.
   Elle doit renvoyer "True" si *item* est dans *self* et "False"
   sinon. Pour les tableaux de correspondances, seules les clés sont
   considérées (pas les valeurs des paires clés-valeurs).

   Pour les objets qui ne définissent pas "__contains__()", les tests
   d'appartenance essaient d'abord d'itérer avec "__iter__()" puis
   avec le vieux protocole d'itération sur les séquences *via*
   "__getitem__()", reportez-vous à cette section dans la référence du
   langage.


3.3.8. Émulation de types numériques
------------------------------------

Les méthodes suivantes peuvent être définies pour émuler des objets
numériques. Les méthodes correspondant à des opérations qui ne sont
pas autorisées pour la catégorie de nombres considérée (par exemple,
les opérations bit à bit pour les nombres qui ne sont pas entiers)
doivent être laissées indéfinies.

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)
object.__mod__(self, other)
object.__divmod__(self, other)
object.__pow__(self, other[, modulo])
object.__lshift__(self, other)
object.__rshift__(self, other)
object.__and__(self, other)
object.__xor__(self, other)
object.__or__(self, other)

   Ces méthodes sont appelées pour implémenter les opérations
   arithmétiques binaires ("+", "-", "*", "@", "/", "//", "%",
   "divmod()", "pow()", "**", "<<", ">>", "&", "^", "|"). Par exemple,
   pour évaluer l'expression "x + y", où *x* est une instance d'une
   classe qui possède une méthode "__add__()", "x.__add__(y)" est
   appelée. La méthode "__divmod__()" doit être l'équivalent d'appeler
   "__floordiv__()" et "__mod__()" ; elle ne doit pas être reliée à
   "__truediv__()". Notez que "__pow__()" doit être définie de manière
   à accepter un troisième argument optionnel si la version ternaire
   de la fonction native "pow()" est autorisée.

   Si l'une de ces méthodes n'autorise pas l'opération avec les
   arguments donnés, elle doit renvoyer "NotImplemented".

object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)

   Ces méthodes sont appelées pour implémenter les opérations
   arithmétiques binaires ("+", "-", "*", "@", "/", "//", "%",
   "divmod()", "pow()", "**", "<<", ">>", "&", "^", "|") avec des
   opérandes renversés (intervertis). Ces fonctions ne sont appelées
   que si l'opérande de gauche n'autorise pas l'opération
   correspondante [3] et si les opérandes sont de types différents
   [4]. Par exemple, pour évaluer l'expression "x - y", où *y* est une
   instance d'une classe qui possède une méthode "__rsub__()",
   "y.__rsub__(x)" est appelée si "x.__sub__(y)" renvoie
   *NotImplemented*.

   Notez que la fonction ternaire "pow()" n'essaie pas d'appeler
   "__rpow__()" (les règles de coercition seraient trop compliquées).

   Note:

     Si le type de l'opérande de droite est une sous-classe du type de
     l'opérande de gauche et que cette sous-classe fournit une
     implémentation différente de la méthode symétrique pour
     l'opération, cette méthode est appelée avant la méthode
     originelle de l'opérande gauche. Ce comportement permet à des
     sous-classes de surcharger les opérations de leurs ancêtres.

object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__imatmul__(self, other)
object.__itruediv__(self, other)
object.__ifloordiv__(self, other)
object.__imod__(self, other)
object.__ipow__(self, other[, modulo])
object.__ilshift__(self, other)
object.__irshift__(self, other)
object.__iand__(self, other)
object.__ixor__(self, other)
object.__ior__(self, other)

   Ces méthodes sont appelées pour implémenter les assignations
   arithmétiques augmentées ("+=", "-=", "*=", "@=", "/=", "//=",
   "%=", "**=", "<<=", ">>=", "&=", "^=", "|="). Ces méthodes doivent
   essayer d'effectuer l'opération « sur place » (c'est-à-dire de
   modifier *self*) et de renvoyer le résultat (qui peut être, mais
   pas nécessairement, *self*). Si une méthode spécifique n'est pas
   définie, l'assignation augmentée se replie vers la méthode normale
   correspondante. Par exemple, si *x* est une instance d'une classe
   qui possède une méthode "__iadd__()", "x += y" est équivalent à "x
   = x.__iadd__(y)". Sinon, "x.__add__(y)" et "y.__radd__(x)" sont
   essayées, comme pour l'évaluation de "x + y". Dans certaines
   situations, les assignations augmentées peuvent causer des erreurs
   inattendues (voir Pourquoi a_tuple[i] += ['item'] lève-t-il une
   exception alors que l'addition fonctionne ?), mais ce comportement
   est en fait partie intégrante du modèle de données.

   Note:

     en raison d'un bogue dans le mécanisme de distribution de "**=",
     une classe qui définit "__ipow__()" mais qui renvoie
     "NotImplemented" n'arriverait pas à se replier sur "x.__pow__(y)"
     et "y.__rpow__(x)". Ce bogue est corrigé dans Python 3.10.

object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

   Appelée pour implémenter les opérations arithmétiques unaires ("-",
   "+", "abs()" et "~").

object.__complex__(self)
object.__int__(self)
object.__float__(self)

   Appelées pour implémenter les fonctions natives "complex()",
   "int()" et "float()". Elles doivent renvoyer une valeur du type
   approprié.

object.__index__(self)

   Appelée pour implémenter "operator.index()" et lorsque Python a
   besoin de convertir sans perte un objet numérique en objet entier
   (pour un découpage ou dans les fonctions natives "bin()", "hex()"
   et "oct()"). La présence de cette méthode indique que l'objet
   numérique est un type entier. Elle doit renvoyer un entier.

   Si "__int__()", "__float__()" et "__complex__()" ne sont pas
   définies, alors les fonctions natives "int()", "float()" et
   "complex()" redirigent par défaut vers "__index__()".

object.__round__(self[, ndigits])
object.__trunc__(self)
object.__floor__(self)
object.__ceil__(self)

   Appelée pour implémenter la fonction native "round()" et les
   fonctions du module "math" "trunc()", "floor()" et "ceil()". À
   moins que *ndigits* ne soit passé à "__round__()", toutes ces
   méthodes doivent renvoyer la valeur de l'objet tronquée pour donner
   un "Integral" (typiquement un "int").

   La fonction native "int()" se replie sur "__trunc__()" dans le cas
   où ni "__int__()" ni "__index__()" ne sont définies.


3.3.9. Gestionnaire de contexte With
------------------------------------

Un *gestionnaire de contexte* est un objet qui met en place un
contexte prédéfini au moment de l'exécution de l'instruction "with".
Le gestionnaire de contexte gère l'entrée et la sortie de ce contexte
d'exécution pour tout un bloc de code. Les gestionnaires de contextes
sont normalement invoqués en utilisant une instruction "with" (décrite
dans la section L'instruction with), mais ils peuvent aussi être
directement invoqués par leurs méthodes.

Les utilisations classiques des gestionnaires de contexte sont la
sauvegarde et la restauration d'états divers, le verrouillage et le
déverrouillage de ressources, la fermeture de fichiers ouverts, etc.

Pour plus d'informations sur les gestionnaires de contexte, lisez Le
type gestionnaire de contexte.

object.__enter__(self)

   Entre dans le contexte d'exécution relatif à cet objet.
   L'instruction "with" lie la valeur de retour de cette méthode à une
   (ou plusieurs) cible spécifiée par la clause "as" de l'instruction,
   si elle est spécifiée.

object.__exit__(self, exc_type, exc_value, traceback)

   Sort du contexte d'exécution relatif à cet objet. Les paramètres
   décrivent l'exception qui a causé la sortie du contexte. Si l'on
   sort du contexte sans exception, les trois arguments sont à "None".

   Si une exception est indiquée et que la méthode souhaite supprimer
   l'exception (c'est-à-dire qu'elle ne veut pas que l'exception soit
   propagée), elle doit renvoyer "True". Sinon, l'exception est
   traitée normalement à la sortie de cette méthode.

   Notez qu'une méthode "__exit__()" ne doit pas lever à nouveau
   l'exception qu'elle reçoit ; c'est du ressort de l'appelant.

Voir aussi:

  **PEP 343** — L'instruction "with"
     La spécification, les motivations et des exemples de
     l'instruction "with" en Python.


3.3.10. Recherche des méthodes spéciales
----------------------------------------

Pour les classes définies par le développeur, l'invocation implicite
de méthodes spéciales n'est garantie que si ces méthodes sont définies
par le type d'objet, pas dans le dictionnaire de l'objet instance. Ce
comportement explique pourquoi le code suivant lève une exception :

   >>> class C:
   ...     pass
   ...
   >>> c = C()
   >>> c.__len__ = lambda: 5
   >>> len(c)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: object of type 'C' has no len()

La raison de ce comportement vient de certaines méthodes spéciales
telles que "__hash__()" et "__repr__()" qui sont implémentées par tous
les objets, y compris les objets types. Si la recherche effectuée par
ces méthodes utilisait le processus normal de recherche, elles ne
fonctionneraient pas si on les appelait sur l'objet type lui-même :

   >>> 1 .__hash__() == hash(1)
   True
   >>> int.__hash__() == hash(int)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: descriptor '__hash__' of 'int' object needs an argument

Essayer d'invoquer une méthode non liée d'une classe de cette manière
est parfois appelé « confusion de métaclasse » et se contourne en
shuntant l'instance lors de la recherche des méthodes spéciales :

   >>> type(1).__hash__(1) == hash(1)
   True
   >>> type(int).__hash__(int) == hash(int)
   True

En plus de shunter les attributs des instances pour fonctionner
correctement, la recherche des méthodes spéciales implicites shunte
aussi la méthode "__getattribute__()" même dans la métaclasse de
l'objet :

   >>> class Meta(type):
   ...     def __getattribute__(*args):
   ...         print("Metaclass getattribute invoked")
   ...         return type.__getattribute__(*args)
   ...
   >>> class C(object, metaclass=Meta):
   ...     def __len__(self):
   ...         return 10
   ...     def __getattribute__(*args):
   ...         print("Class getattribute invoked")
   ...         return object.__getattribute__(*args)
   ...
   >>> c = C()
   >>> c.__len__()                 # Explicit lookup via instance
   Class getattribute invoked
   10
   >>> type(c).__len__(c)          # Explicit lookup via type
   Metaclass getattribute invoked
   10
   >>> len(c)                      # Implicit lookup
   10

En shuntant le mécanisme de "__getattribute__()" de cette façon, cela
permet d'optimiser la vitesse de l'interpréteur moyennant une certaine
manœuvre dans la gestion des méthodes spéciales (la méthode spéciale
*doit* être définie sur l'objet classe lui-même afin d'être invoquée
de manière cohérente par l'interpréteur).


3.4. Coroutines
===============


3.4.1. Objets *attendables* (*awaitable*)
-----------------------------------------

Un objet *awaitable* implémente généralement une méthode
"__await__()". Les objets *coroutine* renvoyés par les fonctions
"async def" sont des *attendables* (*awaitable*).

Note:

  The *generator iterator* objects returned from generators decorated
  with "types.coroutine()" or "asyncio.coroutine()" are also
  awaitable, but they do not implement "__await__()".

object.__await__(self)

   Doit renvoyer un *itérateur*. Doit être utilisé pour implémenter
   les objets *awaitable*. Par exemple, "asyncio.Future" implémente
   cette méthode pour être compatible avec les expressions "await".

Nouveau dans la version 3.5.

Voir aussi:

  **PEP 492** pour les informations relatives aux objets *attendables*
  (*awaitable*).


3.4.2. Objets coroutines
------------------------

Les objets *coroutine* sont des objets *awaitable*. L'exécution d'une
coroutine peut être contrôlée en appelant "__await__()" et en itérant
sur le résultat. Quand la coroutine a fini de s'exécuter et termine,
l'itérateur lève "StopIteration" et l'attribut "value" de l'exception
contient la valeur de retour. Si la coroutine lève une exception, elle
est propagée par l'itérateur. Les coroutines ne doivent pas lever
directement des exceptions "StopIteration" non gérées.

Les coroutines disposent aussi des méthodes listées ci-dessous,
analogues à celles des générateurs (voir Méthodes des générateurs-
itérateurs). Cependant, au contraire des générateurs, vous ne pouvez
pas itérer directement sur des coroutines.

Modifié dans la version 3.5.2: Utiliser *await* plus d'une fois sur
une coroutine lève une "RuntimeError".

coroutine.send(value)

   Démarre ou reprend l'exécution d'une coroutine. Si *value* est
   "None", c'est équivalent à avancer l'itérateur renvoyé par
   "__await__()". Si *value* ne vaut pas "None", cette méthode appelle
   la méthode "send()" de l'itérateur qui a causé la suspension de la
   coroutine. Le résultat (valeur de retour, "StopIteration" ou une
   autre exception) est le même que lorsque vous itérez sur la valeur
   de retour de "__await__()", décrite ci-dessus.

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

   Lève l'exception spécifiée dans la coroutine. Cette méthode délègue
   à la méthode "throw()" de l'itérateur qui a causé la suspension de
   la coroutine, s'il possède une telle méthode. Sinon, l'exception
   est levée au point de suspension. Le résultat (valeur de retour,
   "StopIteration" ou une autre exception) est le même que lorsque
   vous itérez sur la valeur de retour de "__await__()", décrite ci-
   dessus. Si l'exception n'est pas gérée par la coroutine, elle est
   propagée à l'appelant.

coroutine.close()

   Demande à la coroutine de faire le ménage et de se terminer. Si la
   coroutine est suspendue, cette méthode délègue d'abord à la méthode
   "close()" de l'itérateur qui a causé la suspension de la coroutine,
   s'il possède une telle méthode. Ensuite, elle lève "GeneratorExit"
   au point de suspension, ce qui fait le ménage dans la coroutine
   immédiatement. Enfin, la coroutine est marquée comme ayant terminé
   son exécution, même si elle n'a jamais démarré.

   Les objets coroutines sont automatiquement fermés en utilisant le
   processus décrit au-dessus au moment où ils sont détruits.


3.4.3. Itérateurs asynchrones
-----------------------------

Un *itérateur asynchrone* peut appeler du code asynchrone dans sa
méthode "__anext__".

Les itérateurs asynchrones peuvent être utilisés dans des instructions
"async for".

object.__aiter__(self)

   Doit renvoyer un objet *itérateur asynchrone*.

object.__anext__(self)

   Doit renvoyer un *attendable* (*awaitable*) qui se traduit par la
   valeur suivante de l'itérateur. Doit lever une "StopAsyncIteration"
   quand l'itération est terminée.

Un exemple d'objet itérateur asynchrone :

   class Reader:
       async def readline(self):
           ...

       def __aiter__(self):
           return self

       async def __anext__(self):
           val = await self.readline()
           if val == b'':
               raise StopAsyncIteration
           return val

Nouveau dans la version 3.5.

Modifié dans la version 3.7: avant Python 3.7, "__aiter__()" pouvait
renvoyer un *attendable* (*awaitable*) qui se résolvait
potentiellement en un *itérateur asynchrone*.À partir de Python 3.7,
"__aiter__()" doit renvoyer un objet itérateur asynchrone. Renvoyer
autre chose entraine une erreur "TypeError".


3.4.4. Gestionnaires de contexte asynchrones
--------------------------------------------

Un *gestionnaire de contexte asynchrone* est un *gestionnaire de
contexte* qui est capable de suspendre son exécution dans ses méthodes
"__aenter__" et "__aexit__".

Les gestionnaires de contexte asynchrones peuvent être utilisés dans
des instructions "async with".

object.__aenter__(self)

   Sémantiquement équivalente à "__enter__()", à la seule différence
   près qu'elle doit renvoyer un *attendable* (*awaitable*).

object.__aexit__(self, exc_type, exc_value, traceback)

   Sémantiquement équivalente à "__exit__()", à la seule différence
   près qu'elle doit renvoyer un *attendable* (*awaitable*).

Un exemple de classe de gestionnaire de contexte asynchrone :

   class AsyncContextManager:
       async def __aenter__(self):
           await log('entering context')

       async def __aexit__(self, exc_type, exc, tb):
           await log('exiting context')

Nouveau dans la version 3.5.

-[ Notes de bas de page ]-

[1] Il *est* possible, dans certains cas, de changer le type d'un
    objet, sous certaines conditions. Cependant, ce n'est généralement
    pas une bonne idée car cela peut conduire à un comportement très
    étrange si ce n'est pas géré correctement.

[2] Les méthodes "__hash__()", "__iter__()", "__reversed__()" et
    "__contains__()" ont une gestion particulière pour cela ; les
    autres lèvent toujours "TypeError", mais le font en considérant
    que "None" n'est pas un appelable.

[3] *n'autorise pas* signifie ici que la classe ne possède pas de
    méthode adéquate ou que la méthode renvoie "NotImplemented".
    N'assignez pas "None" à la méthode si vous voulez un repli vers la
    méthode symétrique de l'opérande de droite — cela aurait pour
    effet de *bloquer* un tel repli.

[4] Pour des opérandes de même type, on considère que si la méthode
    originelle (telle que "__add__()") échoue, alors l'opération en
    tant que telle n'est pas autorisée et donc la méthode symétrique
    n'est pas appelée.
