IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Python, de zéro


précédentsommairesuivant

IV. Introduction informelle à Python

Dans les exemples qui suivent et jusqu’à la fin de ce tutoriel, les entrées et sorties se distinguent par la présence ou l’absence d’invite (>>> et ...). Pour reproduire les exemples, vous devez taper tout ce qui est après l’invite, au moment où celle-ci apparaît. Notez qu’une invite secondaire affichée seule sur une ligne dans un exemple indique que vous devez entrer une ligne vide ; ceci est utilisé pour terminer une commande multilignes.

Toutefois, pour les codes un peu plus longs, les premières lignes ne seront pas précédées d’invite (>>>) qui ne sera indiquée que sur les 2 ou 3 dernières lignes de l’exemple. Ensuite, à partir de là première ligne contenant une invite (>>>), les lignes qui n’affichent pas d’invite sont les sorties de l’interpréteur.

Et les exemples vraiment très longs ou assez complexes seront écrits sous forme de script Python ce qui sera indiqué par la présence d’une ligne #!/usr/bin/env python en début de l’exemple. Et si le résultat est montré, il le sera alors en dessous dans un bloc séparé du script et intitulé à cet effet.

IV-1. Les variables

IV-1-a. Préambule

Une variable sert à mémoriser une valeur pour la réutiliser ultérieurement. Son nom reste libre à quelques exceptions près liées aux obligations du langage et de sa syntaxe. Le nom d’une variable doit :

  • commencer par une lettre (majuscule ou minuscule) ;
  • ne pas contenir de caractères spéciaux tels que étoile, dollar, accolade ; ni de caractère de ponctuation tels la virgule, le point, etc. Le caractère souligné (_) reste cependant autorisé ;
  • ne pas contenir d’espace ;
  • ne pas être un mot clef de Python.

Une variable se crée en mettant son nom, suivi du caractère égal (=) suivi de la valeur à stocker. Cette valeur peut elle-même provenir d’une autre variable ou d’une expression (expression pouvant faire intervenir elle‑même des variables).

 
Sélectionnez
1.
2.
3.
4.
5.
>>> a=5
>>> b=6
>>> c=a*b
>>> c
30

L’évaluation de l’expression se faisant toujours avant l’affectation, une variable peut s’utiliser elle‑même pour modifier sa valeur.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> a=5
>>> a=a+1
>>> a=a*2
>>> a
12

Dans ce cas particulier, on peut alors utiliser un raccourci syntaxique équivalent en remplaçant var=var opérateur valeur par var operateur= valeur (pas d’espace entre operateur et =).

 
Sélectionnez
1.
2.
3.
4.
5.
>>> a=5
>>> a+=1
>>> a*=2
>>> a
12

IV-1-b. Le typage

Python est un langage dynamiquement typé. Les variables prennent instantanément le type de leur opérande lors de l’affectation ; Python déterminant le type adéquat par la syntaxe de l’opérande utilisé.

La récupération du type d’une variable peut se faire par la fonction type() :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
>>> a=5
>>> b=5.0
>>> c="toto"
>>> d=b"tutu"
>>> type(a)
<class 'int'>
>>> type(b)
<class 'float'>
>>> type(c)
<class 'str'>

Les types disponibles nativement sont les suivants :

  • les entiers (type int). Ils concernent les nombres entiers relatifs (positifs et négatifs). Leur plage de valeur est virtuellement infinie dans Python 3 (ne dépend que de la mémoire de l’ordinateur) tandis qu'elle est limitée dans Python 2 (de l’ordre de -262 à 262). C’est le type utilisé par défaut lorsque l’opérande est un nombre entier.
    Ils peuvent s’écrire sous leur forme naturelle (2, 3, 12, 17, etc.) ; sous forme octale en les faisant précéder de 0o ou 0O (0o2, 0o3, 0O10, 0O21, etc.) ; sous forme hexadécimale en les faisant précéder de 0x ou 0X (0x2, 0x3, 0XB, 0X11) ; ou même sous forme binaire en les faisant précéder de 0b ou 0B (0b10, 0b11, 0B1100, 0B100001).
    De plus, cette écriture peut s’agrémenter d’un ou plusieurs soulignés (_) permettant de faciliter la lecture du nombre si on l’emploie par exemple pour représenter le séparateur des milliers, millions (123_456_789 au lieu de 123456789),

  • les entiers (type long). Ce type spécifique à Python 2 et disparu dans Python 3 (car intégré dans les int) concerne les grands nombres entiers relatifs (positifs et négatifs). Leur plage de valeur est virtuellement infinie (ne dépend que de la mémoire de l’ordinateur). Ce type est appliqué si l’opérande contient un nombre entier suivi de la lettre L ou l (2l, 3l, 17L, etc.) ;

  • les nombres à virgule flottante (type float). Ils concernent les nombres décimaux. Leur nom vient du fait que pour deux décimaux distincts, la virgule décimale n’est pas nécessairement à la même position (elle « flotte »). Ce type est appliqué dès que l’opérande contient un nombre incluant un point (séparateur décimal anglo‑saxon). Leur plage de valeur va d’environ 10‑308 jusqu’à environ 10308 (y compris dans les négatifs). Ce type n’offre pas d’écriture sous forme binaire, octale ou hexadécimale, mais offre toutefois le séparateur souligné (2.5, 3.17, 123_456.05, etc.) ;

  • les chaînes de caractères (type str), les tuples (type tuple), les listes (type list), les ensembles (type set), les dictionnaires (type dict), les booléens (type bool), les none (type NoneType). Ils seront vus plus en détail ultérieurement.

Tous les types natifs Python (int, float, str, etc.) possèdent des fonctions portant le même nom permettant alors de forcer ou caster (to cast=jouer un rôle) un type particulier à la place du type pris par défaut. Il suffit d'appeler la fonction du type demandé en y passant la valeur à forcer.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
>>> a=5
>>> b=float(a)
>>> c=str(b)
>>> d=bytes(c)
>>> type(a)
<class 'int'>
>>> type(b)
<class 'float'>
>>> type(c)
<class 'str'>

En plus des nombres entiers et décimaux, Python gère les nombres complexes, en utilisant le suffixe j ou J pour indiquer la partie imaginaire (exemple a=3+5j). Et il existe des librairies spécifiques pour gérer les nombres décimaux avec exactitude (ce point sera décrit ultérieurement) et les nombres rationnels.

IV-1-c. Les annotations

Depuis la version 3.5 de Python, les variables peuvent être annotées par le programmeur, c’est-à-dire qu’il peut y rajouter le type qu’il a prévu pour la variable.

Cela se fait en rajoutant :nom_du_type_attendu après le nom de la variable et avant l’opérateur = de l’affectation.

Exemple :

Syntaxe habituelle

 
Sélectionnez
1.
a=5

Nouvelle syntaxe possible

 
Sélectionnez
1.
a:int=5

De plus, cette syntaxe accepte plusieurs types à mettre dans un tuple.

 
Sélectionnez
1.
2.
a:(int,float)=5
b:(int,float)=6.5

Cette notation est facultative, mais si elle est appliquée, le typage indiqué doit correspondre à une liste de mots clefs précis permettant d’englober tous les types connus de Python 3. On trouvera donc int, float, bytes, str, bool, tuple, list, set, dict et None correspondants aux types des mêmes noms ; auxquels viendront se greffer callable représentant un paramètre appelable (généralement une fonction), object représentant un paramètre de type objet (sera vu ultérieurement) et any indiquant un paramètre de type indéterminé ou changeable. Cette liste peut aussi contenir les noms des objets personnels (sera vu ultérieurement) créés en amont dans le code.

Néanmoins ces indications sont, pour l’instant, purement informatives. Python ne contrôle donc pas la correspondance entre ce qui est indiqué comme type prévu et ce qui est réellement affecté dans la variable, mais cela risque de changer dans les versions futures.

 
Sélectionnez
1.
2.
a:int="toto"                 # Une string là où il est annoté un int
b:str=123                    # Un int là où il est annoté une string

IV-2. Les opérateurs

IV-2-a. Arithmétiques et logiques

Les opérateurs arithmétiques et logiques permettent d’effectuer des opérations (le plus souvent mathématiques). On trouve :

  • l’addition (+). Ex : 2+3 => 5 ;

  • la soustraction (-). Ex : 32 => 1 ;

  • la multiplication (*). Ex : 3*4 => 12 ;

  • la division (/). Pour cette dernière, dans Python 2, l’opération s’effectue selon le type le plus large des opérandes à diviser (pour deux entiers cela sera alors une division entière), tandis que dans Python 3, quel que soit le type des opérandes (tout en restant des numériques) l’opération est une vraie division décimale. Ex 11/4 => 2 sous Python 2 et 2.75 sous Python 3 ;

  • la division euclidienne (//). Division calculée dans le type le plus large des opérandes à diviser (pour deux entiers cela sera alors une division entière), mais donnant quoiqu'il arrive un résultat arrondi à l’entier inférieur. Ex : 11//4 => 2 et 11.0//4 => 2.0 ;

  • le modulo (%) qui est le reste d’une division entière. Ex : 11%4 => 3 ;

  • la puissance (**) appelée aussi « exposant ». Ex : 11**4 => 14641. Elle peut s’utiliser avec des opérandes flottants (ce qui donne des racines nièmes) ainsi que sur des négatifs (ce qui peut alors donner des nombres complexes) ;

  • le « non » bit à bit (~), qui donne un nombre où tous les bits de l'opérande ont été inversés. Ex : ~123 => 124 (et effectivement, avec la façon de coder les négatifs en informatique aujourd’hui, le résultat de ~x est égal à –x‑1) ;

  • le « et » bits à bits (&), qui donne un nombre composé des bits à 1 communs entre l’opérande de gauche et celui de droite. Ex : 6&5 => 4 ;

  • le « ou inclusif » bits à bits (|), qui donne un nombre composé de tous les bits à 1 présents dans les deux opérandes. Ex : 6|5 => 7 ;

  • le « ou exclusif » bits à bits (^), qui donne un nombre composé des bits à 1 présents uniquement dans l'un des deux opérandes au choix. Ex : 6^5 => 3. Cet opérateur peut aussi se retrouver par composition du not, du & et du | (a^b=a&(~b) | (~a)&b). Ex : 6&(~5| (~6)&5 => 3 ;

  • le décalage de bits à gauche (<<) ou à droite (>>), ce qui équivaut respectivement à une multiplication ou une division euclidienne par 2 élevée à la puissance du décalage. Ex : 11<<4 => 176 (tout comme 11*(2**4)) et 14641>>3 => 1830 (tout comme 14641//(2**3)).

Le résultat des opérations dépend du type des opérandes impliqués et, sauf cas particulier (comme la division dans Python 3 qui pourra donner un flottant même si on ne divise que des entiers), sera toujours du type le plus large des opérandes impliqués. Dans certains cas, il peut même ne plus rien à voir avec une opération mathématique, tout en restant cohérent dans une autre logique (par exemple multiplier une chaîne par un nombre répètera la chaîne autant de fois que le nombre indiqué).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
>>> 2 + 2                  # int + int => int
4
>>> 505 * 6             # int – int * int => int
20
>>> (50 - 5.0 * 6) // 4    # (int – float * int) // int => float
5.0
>>> 17 // 3                # int // int => int
5
>>> 17 // 3.0              # int / float => float (mais la division est restée entière)
5.0
>>> 17 / 3                 # int / int => float (cas particulier de la division Python 3)
5.666666666666667
>>> 17 % 3                 # reste de la division
2
>>> 5 * 3 + 2              # quotient * diviseur + reste => redonne le nombre initial
17

IV-2-b. Relationnels

Les opérateurs relationnels permettent d’effectuer des comparaisons. On trouve :

  • la comparaison d'égalité (== ou !=) qui donne un booléen vrai/faux selon que les opérandes sont égaux ou différents dans leur valeur (et inversement) ;

  • la relation d'ordre (<, >, <=, >=) qui donne un booléen vrai/faux selon que l’opérande de gauche est plus petit, plus grand, plus petit ou égal, plus grand ou égal (et inversement) que l’opérande de droite ;

  • le is qui vérifie si l’opérande de gauche est identique (au sens interne de Python) à l’opérande de droite ;

  • arrivé avec la version 3.8, l'opérateur morse (:=) permet de faire simultanément une affectation et un test dans la même expression. Ainsi, ce qui dans une version précédente se serait écrit v=expression(); if v == valeur: action, peut s'écrire maintenant if v:=expression() == valeur: action. Le nom de cet opérateur vient de sa ressemblance avec les yeux et les dents de l’animal.

IV-2-c. Connecteurs

Les connecteurs peuvent associer ou modifier le sens de l'évaluation. On trouve :

  • le and (vf « et »), qui ne validera l'expression entière que si les expressions situées de part et d'autre sont elles‑mêmes validées,

  • le or (vf « ou »), qui validera l'expression entière si au moins l'une des expressions situées de part et d'autre est elle‑même validée.

Ces deux connecteurs fonctionnent à l'économie. L'évaluation de l'expression s'arrête donc dès qu'une certitude est atteinte dans un sens ou dans l'autre (ex : or Y or Z s'arrête dès le premier True trouvé),

  • le not, qui inverse le sens booléen de l'expression.

À noter : il est possible de chaîner plusieurs opérateurs relationnels. Exemple : < b < c < d renverra vrai si toutes les valeurs sont rangées par ordre croissant (Python remplace automatiquement ce type d'instruction en < b and< c and< d). Cela permet de vérifier si une expression est incluse entre deux valeurs sans avoir à la répéter (expr > x and expr < y devenant alors < expr < y).

IV-2-d. Priorités

Les opérateurs suivent des règles de priorité équivalentes à celles de l’arithmétique. Dans l’ordre croissant la comparaison ; puis les opérateurs bits à bits ; puis le décalage, puis l’addition et la soustraction ; puis la multiplication et la division ; puis les puissances. Et à opérateurs de priorité égale, les opérations se font de la gauche vers la droite…

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
>>> 4 ** 2
16
>>> 16 * 3
48
>>> 48 + 2
50
>>> 2 << 50
2251799813685248
>>> 1 | 2251799813685248
2251799813685249
>>> 1 != 2251799813685249
True
>>> 1 != 1 | 2 << 2 + 3 * 4 ** 2
True

… à moins que des parenthèses ne viennent modifier cet ordre naturel.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
>>> 1 != 1
False
>>> False | 2
2
>>> 2 << 2
8
>>> 8 + 3
11
>>> 11 * 4
44
>>> 44 ** 2
1936
>>> (((((1 != 1) | 2) << 2) + 3) * 4) ** 2
1936

IV-3. Les chaînes de caractères

Au‑delà des nombres, Python sait aussi manipuler des chaînes de caractères, qui peuvent être exprimées de différentes manières. Elles peuvent être écrites entre quotes simples ('...') ou entre guillemets ("...") sans distinction. Et le backslash (\) permet de protéger le caractère d’encadrement lorsqu’il doit apparaître comme caractère de la chaîne.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
>>> 'œufs et pain'            # quotes simples
'œufs et pain'
>>> 'aujourd\'hui'            # le backslash protège la quote simple…
'aujourd’hui'
>>> "aujourd'hui"             # …ou plus simplement utiliser les guillemets
'aujourd’hui'
>>> '"Oui", dit-il.'
'"Oui", dit-il.'
>>> "\"Oui\", dit-il."
'"Oui", dit-il.'

Les chaînes peuvent être concaténées (collées) avec l’opérateur + (plus) et répétées avec l’opérateur * (étoile).

 
Sélectionnez
1.
2.
>>> 'Barba' + 2 * 'pa'        # 'Barba' suivi de 2 fois 'pa'
'Barbapapa'

Les chaînes de caractères peuvent être indicées (accéder aux caractères par leurs positions) en utilisant la notation « crochets » utilisée généralement dans les tableaux (chaine[position]). Le premier caractère d’une chaîne est à la position 0.

Afin de simplifier les choses, il n’existe pas de type distinct pour les caractères. Un caractère est simplement une chaîne de longueur 1.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> word='Python'
>>> word[0]                   # Caractère à la position 0 (le premier)
'P'
>>> word[5]                   # Caractère à la position 5 (le sixième)
'n'

Les indices peuvent également être négatifs ce qui les décompte alors en partant de la fin.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> word[-1]                 # Dernier caractère
'n'
>>> word[-2]                 # Avant-dernier caractère
'o'
>>> word[-6]                 # Sixième en partant de la fin
'P'

Notez que 0 ne pouvant pas être utilisé pour partir de la fin (car il est égal à 0), les indices négatifs commencent à 1.

En plus de l’indexation utilisée pour obtenir les caractères individuellement, le découpage (slicing) permet d’obtenir une sous-chaîne par extraction de tous les caractères situés entre deux positions.

 
Sélectionnez
1.
2.
3.
4.
>>> word[0:2]                # De la position 0 (incluse) à 2 (exclue)
'Py'
>>> word[2:5]                # De la position 2 (incluse) à 5 (exclue)
'tho'

Le saut entre les positions peut être spécifié en 3e paramètre…

 
Sélectionnez
1.
2.
>>> word[1:6:2]              # De la position 1 (incluse) à 6 (exclue) par pas de 2
'yhn'

… ce qui permet alors de traiter la chaîne dans le sens inverse.

 
Sélectionnez
1.
2.
>>> word[5:0:-2]             # De la position 5 (incluse) à 0 (exclue) par pas de ‑2
'nhy'

Notez que le début ou la fin (ou les deux) peuvent être omis (ou mis à None). Si le début est omis ou None, alors le découpage commence au premier caractère inclus. Si la fin est omise, alors le découpage s’arrête au dernier caractère inclus. De plus, la notion « premier » ou « dernier » dépend du sens de traitement donné par le 3e paramètre.

 
Sélectionnez
1.
2.
3.
4.
>>> word[::2]                # Du début à la fin par pas de 2
'Pto'
>>> word[::-2]               # De la fin vers le début par pas de ‑2
'nhy'

Inclure le début et exclure la fin permet que chaine[:i] + chaine[i:] soit toujours égal à chaine.

 
Sélectionnez
1.
2.
3.
4.
>>> word[:2] + word[2:]
'Python'
>>> word[None:4] + word[4:None]
'Python'

Les chaînes de caractères, en Python, ne peuvent pas être modifiées. On dit qu’elles sont immuables (par opposition aux types « mutables »). Tenter de placer un caractère quelconque à un indice ou à un slice dans une chaîne produit une exception.

 
Sélectionnez
1.
2.
3.
4.
>>> word[0]='J'
TypeError: 'str' object does not support item assignment
>>> word[2:]='py'
TypeError: 'str' object does not support item assignment

Le seul moyen de remplacer tout ou partie d’une chaîne est d’en créer une nouvelle à partir de la première, quitte ensuite à la réaffecter dans la même variable.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> 'J' + word[1:]
'Jython'
>>> word=word[2:] + 'py'            # Rappel: la variable d’origine contient "Python"
>>> word
'thonpy'

La fonction native len() renvoie la longueur d’une chaîne (nombre de caractères).

 
Sélectionnez
1.
2.
3.
>>> s='supercalifragilisticexpialidocious'
>>> len(s)
34

L'opérateur in (inverse not in) permet de vérifier l'existence (ou la non‑existence) d'une sous-chaîne dans une chaîne.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> s='abracadabra'
>>> 'bra' in s
True
>>> 'ca' not in s
False

IV-4. Les tuples

Python connaît différents types de données combinées, utilisés pour regrouper plusieurs valeurs. Le plus simple à appréhender est le tuple, qui peut être représenté comme une suite de valeurs (éléments) séparées par des virgules. Il s’apparente aux tableaux des autres langages.

Les éléments sont ordonnés (la restitution se fait dans le même ordre que l’ordre de création).

Les éléments d’un tuple ne sont pas obligatoirement tous du même type, bien qu’à l’usage ce soit souvent le cas.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> squares=1, 4, 9, 16, 25, "toto"
>>> type(squares)
<class 'tuple'>
>>> squares
(1, 4, 9, 16, 25, 'toto')

Comme on peut le voir, Python rajoute des parenthèses quand il affiche ses tuples afin de bien les faire ressortir. L’usage de parenthèses à la création de tuples est aussi possible et même vivement recommandé pour éviter les erreurs de syntaxe.

 
Sélectionnez
1.
2.
3.
>>> squares=(1, 4, 9, 16, 25, "toto")
>>> type(squares)
<class 'tuple'>

Il devient d'ailleurs obligatoire quand on veut regrouper certains sous‑ensembles comme stocker des tuples dans un tuple.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> domino=((0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2))
>>> type(domino)
<class 'tuple'>
>>> domino
((0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2))

C’est pourquoi le programmeur Python prend rapidement l’habitude de toujours encadrer ses tuples de parenthèses. Mais notez bien que c’est la virgule qui fait le tuple et non les parenthèses.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> a=(1)
>>> type(a)
<class 'int'>
>>> b=(1,)
>>> type(b)
<class 'tuple'>

Comme les chaînes de caractères (et tout autre type de séquence), les tuples peuvent être indicés et découpés.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
>>> squares=(1, 4, 9, 16, 25, "toto")
>>> squares[0]                      # index (renvoie un item)
1
>>> squares[-1]
'toto'
>>> squares[-3:]                    # slice (renvoie un nouveau tuple)
(16, 25, 'toto')

Toutes les opérations par tranches renvoient un nouveau tuple copié à partir du premier.

 
Sélectionnez
1.
2.
>>> squares[:]
(1, 4, 9, 16, 25, 'toto')

De même que pour les chaînes, les tuples acceptent aussi certaines opérations comme la concaténation…

 
Sélectionnez
1.
2.
3.
>>> squares=(1, 4, 9, 16, 25, "toto")
>>> squares + (36, 49, 64, 81, 100)
(1, 4, 9, 16, 25, 'toto', 36, 49, 64, 81, 100)

…ou la multiplication.

 
Sélectionnez
1.
2.
3.
>>> datas=(2, 3) * 5
>>> datas
(2, 3, 2, 3, 2, 3, 2, 3, 2, 3)

De même que pour les chaînes, les tuples sont immuables : il est impossible de changer leur contenu…

 
Sélectionnez
1.
2.
3.
>>> squares=(1, 4, 9, 16, 25, "toto")
>>> squares[0]=0
TypeError: 'tuple' object does not support item assignment

…mais de même que pour les chaînes, il est possible de remplacer un tuple déjà existant par un autre en jouant avec les opérations de Python pour récupérer les éléments voulus.

 
Sélectionnez
1.
2.
3.
4.
>>> squares=(1, 4, 9, 16, 25, "toto")
>>> squares=(0,) + square[:-1]
>>> squares
(0, 1, 4, 9, 16, 25)

La primitive len() et les opérateurs in/not in s’appliquent aussi aux tuples.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> letters=('a', 'b', 'c', 'd')
>>> len(letters)
4
>>> "c" in letters
True

Puisque chaque élément d’un tuple peut être n’importe quel élément Python, il est donc possible d’imbriquer des tuples (de créer des tuples contenant d’autres tuples)…

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
>>> alpha=('a', 'b', 'c')
>>> num=(1, 2, 3)
>>> x=(alpha, num)
>>> x
(('a', 'b', 'c'), (1, 2, 3))
>>> type(x)
<class 'tuple'>
>>> x[0]
('a', 'b', 'c')
>>> type(x[0])
<class 'tuple'
>>>> x[1]
(1, 2, 3)
>>> type(x[1])
<class 'tuple'
>>> x[0][1]
'b'
>>> x[1][2]
3

… ce qui ouvre la voie à l’utilisation de containers multidimensionnels.

Le contenu d’un tuple peut être distribué dans des variables distinctes (unpacking) à condition d’avoir autant de variables que ce que le tuple contient d’éléments.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> n=(1, 2, 3)
>>> (x, y, z)=n
>>> x
1
>>> y
2
>>> z
3

Ce mécanisme peut être judicieusement utilisé pour permuter deux variables sans passer par une troisième.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
>>> x=123
>>> y=456
>>> (x, y)
(123, 456)
>>> (x, y)=(y, x)
>>> (x, y)
(456, 123)

Tout comme pour les types standards, le tuple possède sa propre fonction tuple() permettant de caster (forcer) une expression en tuple.

 
Sélectionnez
1.
2.
3.
>>> squares=tuple((1, 4, 9, 16, 25, "toto"))
>>> type(squares)
<class 'tuple'>

On remarquera que tuple() étant une fonction, il faut lui mettre des parenthèses pour demander son exécution. Mais son paramètre étant ici un tuple (qui lui aussi utilise des parenthèses pour sa syntaxe de création), cela conduit alors l’instruction à avoir deux jeux de parenthèses dans sa syntaxe.

Alors OK ça semble idiot de forcer un tuple à être un tuple, mais on verra plus tard qu'il existe des objets susceptibles de contenir plusieurs éléments et là le cast deviendra utile pour forcer ces éléments à apparaître concrètement.

IV-5. Les listes

La liste peut être vue comme une extension du tuple qui autorise le rajout, la modification ou la suppression d’éléments. Celui qui sait manipuler le tuple peut alors aisément se tourner vers la liste qui fournira les mêmes services de base tout en y rajoutant les outils permettant sa modification.

La syntaxe de création d’une liste est la même que pour le tuple, excepté que les éléments sont encadrés de crochets et non de parenthèses. De plus, contrairement au tuple où les parenthèses sont facultatives (mais fortement conseillées), les crochets pour les listes sont obligatoires (sinon on retombe dans la syntaxe du tuple).

 
Sélectionnez
1.
2.
3.
4.
5.
>>> squares=[1, 4, 9, 16, 25, "toto"]
>>> type(squares)
<class 'list'>
>>> squares
[1, 4, 9, 16, 25, 'toto']

Comme les chaînes de caractères et les tuples (et tout autre type de séquence), les listes peuvent être indicées et découpées.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> squares[0]                          # index (renvoie un item)
1
>>> squares[-1]
'toto'
>>> squares[-3:]                        # slice (renvoie une nouvelle liste)
[16, 25, 'toto']

Mais à la différence des chaînes et tuples qui sont immuables, les listes sont mutables : il est donc possible de changer leur contenu.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> cubes=[1, 8, 27, 65, 125]           # quelque chose ne va pas…
>>> 4 ** 3                              # le cube de 4 est 64, pas 65!
64
>>> cubes[3]=64                         # on remplace l’élément incorrect
>>> cubes
[1, 8, 27, 64, 125]

S'il est possible de modifier un élément par son indice, il n’est toutefois pas possible de créer un nouvel élément en lui affectant un indice n’existant pas encore. Le rajout d’éléments peut se faire un par un avec la méthode append() ou peut se faire par rajout d’un itérable quelconque (donc chaîne, tuple, liste ou autre) avec la méthode extend().

Dans les deux cas, les éléments ajoutés viennent se mettre en fin de liste.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> cubes.append(343)
>>> cubes.append(8 ** 3)
>>> cubes
[1, 8, 27, 64, 125, 343, 512]
>>> cubes.extend([729, 10 ** 3])
>>> cubes.extend((11 ** 3,))
>>> cubes
[1, 8, 27, 64, 125, 343, 512, 729, 1000, 1331]

Il est aussi possible d’insérer un élément à une position particulière avec la méthode insert(). L’élément se place à la position demandée en décalant tout le reste de la liste.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
>>> cubes[5]
343
>>> cubes.insert(216, 5)
>>> cubes
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331]
>>> cubes[5]
216
>>> cubes[6]
343

Il est possible de supprimer un ou plusieurs éléments avec l’opérateur del(), qui peut s'utiliser avec ou sans parenthèses. Dans ce cas, les éléments placés à droite des éléments supprimés sont alors décalés pour coller aux éléments à gauche (ce qui n’est pas le cas dans d’autres langages comme le php).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
>>> del(cubes[0])
>>> cubes
[8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331]
>>> cubes[6]
512
>>> del cubes[0:3]
>>> cubes
[125, 216, 343, 512, 729, 1000, 1331]
>>> cubes[6]
1331
>>> cubes[3]
512

Des affectations de tranches sont également possibles, ce qui peut même modifier la taille de la liste ou la vider complètement :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
>>> letters=['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters[2:5]=['C', 'D', 'E']         # remplacer quelques valeurs par d’autres valeurs
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> letters[2:5]=[]                      # remplacer quelques valeurs par une liste vide
>>> letters
['a', 'b', 'f', 'g']
>>> letters[:]=[]                        # remplacer toutes les valeurs par une liste vide
>>> letters
[]

Tout comme pour le tuple et les autres types, la liste possède sa propre fonction list() permettant de caster (forcer) une expression en liste.

 
Sélectionnez
1.
2.
3.
>>> squares=list((1, 4, 9, 16, 25, "toto"))
>>> type(squares)
<class 'list'>

De même que pour le cast en tuple, list() étant une fonction, il faut lui mettre des parenthèses pour demander son exécution. Cependant, son paramètre étant ici un tuple (qui lui aussi utilise des parenthèses pour sa syntaxe de création), cela conduit alors l’instruction à avoir deux jeux de parenthèses dans sa syntaxe.

IV-6. Les ensembles

Python fournit un type de donnée pour les ensembles. Un ensemble est une collection d’éléments ne comportant aucun élément dupliqué (tout élément dupliqué est ignoré lors de la création de l’ensemble ou lors des insertions).

Les éléments sont non ordonnés (l’ordre de restitution ne correspond pas forcément à l’ordre de création). De fait, les ensembles ne permettent pas les accès directs au travers d’indices comme avec les tuples ou les listes.

À noter : un ensemble ne peut contenir que des éléments immuables.

Des utilisations basiques concernent par exemple des tests d’appartenance ou des suppressions de doublons, qui sont bien plus efficaces que sur les listes, car il n’est pas nécessaire de tout traiter pour obtenir un résultat.

Les ensembles supportent également les opérations mathématiques comme les unions, intersections, différences et différences symétriques.

La syntaxe de création d’un ensemble est similaire à celle d’un tuple ou d’une liste excepté que les éléments sont encadrés d’accolades {}.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> fruit={'pomme', 'orange', 'pomme', 'abricot', 'orange', 'banane'}
>>> type(fruit)
<class 'set'>
>>> fruit
set(['orange', 'banane', 'abricot', 'pomme'])        # Les éléments dupliqués ont disparu

Le rajout d’éléments peut se faire un par un avec la méthode add() ou peut se faire par rajout d’un itérable quelconque (donc chaîne, tuple, liste ou autre) avec la méthode update().

Dans tous les cas, si la demande implique l’ajout d’un élément déjà présent, l’élément est alors simplement ignoré.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
>>> fruit.add('poire')
>>> fruit.add('poire')
>>> fruit
set(['orange', 'banane', 'abricot', 'pomme', 'poire'])
>>> fruit.update(('kiwi', 'pomme', 'prune', 'kiwi'))
>>> fruit
set(['orange', 'banane', 'abricot', 'pomme', 'poire', 'kiwi', 'prune'])

Manipulations d'ensembles

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
>>> a={'a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'}
>>> b=set('alacazam')        # Plus facile non ?
>>> a
{'c', 'b', 'd', 'a', 'r'}    # L’ordre initial n’est pas garanti
>>> b
{'c', 'm', 'a', 'l', 'z'}
>>> a – b                    # Lettres dans a qui ne sont pas dans b (b ôté de a)
{'d', 'r', 'b'}
>>> a | b                    # Lettres dans a ou dans b
{'c', 'b', 'd', 'm', 'a', 'r', 'l', 'z'}
>>> a & b                    # Lettres à la fois dans a et dans b
{'a', 'c'}
>>> a ^ b                    # Lettres dans a ou b mais pas dans les deux ((a | b) – (a & b))
{'d', 'b', 'm', 'r', 'l', 'z'}

La primitive len() et les opérateurs in/not in s’appliquent aussi aux ensembles.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> letters={'a', 'b', 'c', 'd'}
>>> len(letters)
4
>>> "c" in letters
True

Tout comme pour le tuple ou la liste et les autres types, l'ensemble possède sa propre fonction set() permettant de caster (forcer) une expression en ensemble.

 
Sélectionnez
1.
2.
3.
>>> fruit=set(('pomme', 'orange', 'pomme', 'abricot', 'orange', 'banane'))
>>> type(fruit)
<class 'set'>

De même que pour le cast en tuple ou en liste, la fonction set() étant une fonction, il faut lui mettre des parenthèses pour demander son exécution. Toutefois son paramètre étant ici un tuple (qui lui aussi utilise des parenthèses pour sa syntaxe de création), cela conduit alors l’instruction à avoir deux jeux de parenthèses dans sa syntaxe.

IV-7. Les dictionnaires

Le dernier type d’agrégation de données de Python est le dictionnaire ; présent parfois dans d’autres langages sous le nom de « mémoire associative » ou de « tableau associatif ».

À la différence des chaînes, tuples et listes ; qui sont indicés par le rang de leurs éléments (les ensembles, eux, n'étant pas indicés du tout), les dictionnaires sont indexés par des clefs, qui, comme les ensembles, ne peuvent être composées que d’éléments immuables.

Le plus simple est de considérer les dictionnaires comme des ensembles de paires clefs+valeur, chaque clef devant être unique au sein d’un dictionnaire.

Jusqu’à Python 3.7, les éléments étaient non ordonnés (l’ordre de restitution ne correspondant pas forcément à l’ordre de création). Depuis Python 3.7, les éléments sont désormais ordonnés par l’ordre de création. Les exemples de ce tutoriel ne seront toutefois pas toujours en adéquation avec cette récente directive.

La syntaxe de création d’un dictionnaire se fait en encadrant les éléments par des accolades {}. Les éléments se placent par paires clef : valeur séparées par des virgules. C’est également de cette façon que les dictionnaires sont affichés en sortie.

Les principales opérations effectuées sur un dictionnaire consistent à stocker une valeur pour une clef et à extraire la valeur correspondant à une clef. On accède aux éléments d’un dictionnaire de la même façon qu’aux éléments de tuples et listes : on indique le nom du dictionnaire puis on place la clef de l’élément voulu entre crochets. On peut donc de cette façon accéder aux éléments existants, mais aussi créer de nouveaux éléments à la volée…

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> tel={"jack" : 4098, "paul" : 4139}
>>> tel["guido"]=4127
>>> type(tel)
<class 'dict'>
>>> tel
{'paul': 4139, 'guido': 4127, 'jack': 4098}
>>> tel["jack"]
4098

… voire même écraser des éléments déjà existants.

 
Sélectionnez
1.
2.
3.
4.
>>> tel={"jack" : 4098, "paul" : 4139}
>>> tel["jack"]=4099
>>> tel["jack"]
4099

Il est également possible de supprimer une paire clef : valeur avec l’opérateur del().

 
Sélectionnez
1.
2.
3.
4.
5.
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> tel["irv"]=4700
>>> del tel["paul"]
>>> tel
{'guido' : 4127, 'irv': 4700, 'jack': 4098}

La méthode keys() d’un dictionnaire renvoie une vue de toutes les clefs utilisées dans le dictionnaire, dans un ordre correspondant à l’ordre interne des éléments. La méthode values() renvoie une vue de toutes les valeurs (a priori dans le même ordre que keys()) et la méthode items() renvoie une vue de tuples clef+valeur (là encore à priori dans le même ordre).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> tel.keys()
dict_keys(['guido', 'irv', 'jack'])
>>> tel.values()
dict_values([4127, 4700, 4098])
>>> tel.items()
dict_items([('guido', 4127),( 'irv', 4700), ('jack', 4098)])

Ces vues s'adaptent au dictionnaire en temps réel. C'est-à-dire que si le dictionnaire évolue, la vue évolue avec.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> k=tel.keys()
>>> k
dict_keys(['paul', 'jack', 'guido'])
>>> del tel["paul"]
>>> k
dict_keys(['jack', 'guido'])

À noter : dans Python 2, ces méthodes ne renvoient pas des vues, mais des listes figées qui n'évoluent donc plus après avoir été invoquées.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> # Exemple Python 2
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> k=tel.keys()
>>> k
['paul', 'jack', 'guido']
>>> del tel["paul"]
>>> k
['paul', 'jack', 'guido']

Dans Python 2, les vues existent aussi et se nomment viewkeys(), viewvalues() et viewitems().

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> # Exemple Python 2
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> tel.viewkeys()
dict_keys(['guido', 'irv', 'jack'])
>>> tel.viewvalues()
dict_values([4127, 4700, 4098])
>>> tel.viewitems()
dict_items([('guido', 4127),( 'irv', 4700), ('jack', 4098)])

Python 2 offre aussi un autre outil pour les dictionnaires : les itérateurs. Ceux-ci se nomment iterkeys(), itervalues() et iteritems().

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> # Exemple Python 2
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> tuple(tel.iterkeys())
('guido', 'irv', 'jack')
>>> tuple(tel.itervalues())
(4127, 4700, 4098)
>>> tuple(tel.iteritems())
(('guido', 4127),( 'irv', 4700), ('jack', 4098))

Toutefois, contrairement aux vues (qui se synchronisent avec le dictionnaire) ou aux listes (qui, une fois créées, se désolidarisent du dictionnaire dont elles sont issues), d’une part ces objets ne sont utilisables qu’une seule fois…

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
>>> # Exemple Python 2
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> k=tel.iterkeys()
>>> tuple(k)
('guido', 'irv', 'jack')
>>> tuple(k)
())

… et d’autre part ces objets ne sont plus utilisables si le dictionnaire dont ils sont issus évolue avant leur utilisation.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> # Exemple Python 2
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> k=tel.iterkeys()
>>> del tel["jack"]
>>> tuple(k)
RuntimeError: dictionary changed size during iteration

Devant les désagréments de ces limitations, il est compréhensible alors que ces méthodes ont disparu dans Python 3 au profit des vues offrant la plus ouverte et la plus souple des différentes technologies.

La fonction len() et les opérateurs in/not in s’appliquent aussi aux dictionnaires (plus exactement ils s’appliquent à ses clefs).

 
Sélectionnez
1.
2.
3.
4.
5.
>>> tel={"jack": 4098, "paul": 4139, "guido" : 4127}
>>> len(tel)
3
>>> "guido" in tel
True

Tout comme pour le tuple, la liste ou l'ensemble et les autres types, le dictionnaire possède sa propre fonction dict() permettant de caster (forcer) une expression en dictionnaire.

 
Sélectionnez
1.
2.
3.
>>> tel=dict((("jack", 5), ("paul", 6)))
type(tel)
<class 'dict'>

De même que pour le cast en tuple, en liste ou en ensemble, dict() étant une fonction, il faut lui mettre des parenthèses pour demander son exécution. Cependant, son paramètre étant ici un tuple (qui lui aussi utilise des parenthèses pour sa syntaxe de création), et chaque élément du tuple étant un couple qui sera traité sous forme de clef+valeur, cela conduit alors l’instruction à avoir trois jeux de parenthèses dans sa syntaxe (premier jeu pour la fonction elle-même, second jeu pour le tuple, et troisième jeu pour chaque couple dudit tuple).

À noter : les accolades pouvant servir tout aussi bien pour symboliser un ensemble qu’un dictionnaire, des accolades vides symbolisent par défaut un dictionnaire. Pour créer un ensemble vide, il faut donc impérativement utiliser la fonction set(). Et de façon plus générale, il est plus prudent et plus lisible (explicite vaut mieux qu’implicite) de passer explicitement par les fonctions nominatives pour créer un container (tuple, liste, ensemble, dictionnaire) vide.

IV-8. True, False, None

Les valeurs True et False (de type bool) servent à représenter des booléens qui peuvent être utilisés lors de tests de vérification d'une particularité sur des ensembles. Ce sont aussi les valeurs représentant une évaluation logique. Il est alors possible de récupérer ces valeurs pour les réutiliser ultérieurement.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
>>> t1=(2 == 2)
>>> t2=(2 > 3)
>>> t1
True
>>> t2
False
>>> t1 or t2
True
>>> t1 and t2
False
>>> type(t1)
<class 'bool'>
>>> type(t2)
<class 'bool'>

Toutefois, cela reste à la base des valeurs entières valant 1 pour True et 0 pour False. Et selon la façon dont on les emploie, cela peut amener à obtenir finalement des valeurs numériques.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
>>> True + True
2
>>> type(False)
<class 'bool'>
>>> type(False + False)
<class 'int'>

Attention : il convient toutefois de ne pas baser ses algorithmes sur les valeurs numériques de True et False, car elles sont issues de conventions qui peuvent évoluer à tout moment.

La valeur None (de type None) sert à officialiser l'existence d'un élément par une valeur neutre. On peut la comparer au NULL du C. Elle permet de créer une variable ou un container sans avoir besoin de spécifier un type particulier sur son contenu.

 
Sélectionnez
1.
2.
3.
4.
5.
>>> v=None
>>> type(v)
<class 'NoneType'>
>>> t1=[None, None, None]
>>> t2=[None,] * 3

À noter : toute expression, bien que ne valant pas explicitement True ou False est quand même utilisable comme un booléen

  • Un int ou un float sont assimilés à True s’ils sont différents de 0 ; sinon ils sont assimilés à False
  • Un str, un tuple, un list, un set ou un dict sont assimilés à True s’ils ne sont pas vides (leur longueur est différente de 0) ; sinon ils sont assimilés à False
  • None est assimilé à False.

En fait, pour résumer, une expression est toujours considérée comme True sauf si elle est False, None, 0 (et tout ce qui en dérive comme une fraction valant 0 ou un complexe valant 0) ; ou si sa longueur vaut 0.

Attention : ces expressions ne sont que considérées comme des booléens ; sans être toutefois du type bool. Ainsi, comparer une chaîne vide avec False sera faux ; mais utiliser une chaîne vide en tant que False dans un test booléen reste possible.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
>>> "" == False
False
>>> "" == True
False
>>> bool("") == False
True
>>> print("ok" if not "" else "bad")
ok

Plus généralement, on ne compare jamais explicitement avec True ou False, car cela revient à comparer avec 1 ou 0 ce qui n’est pas toujours le résultat attendu par le développeur.

 
Sélectionnez
1.
2.
3.
4.
>>> print("ok" if 5 == True else "bad")
bad
>>> print("ok" if 5 is True else "bad")
bad

On peut y arriver en passant par la fonction bool() qui, comme pour toutes les autres fonctions de types, force une expression vers son équivalent booléen…

 
Sélectionnez
1.
2.
>>> print("ok" if bool(5) == True else "bad")
ok

… mais c’est encore plus simple de laisser Python effectuer lui‑même l’évaluation booléenne.

 
Sélectionnez
1.
2.
3.
4.
>>> print("ok" if 5 else "bad")
ok
>>> print("ok" if not 0 else "bad")
ok

IV-9. Les mots clefs

Les mots clefs de Python sont des mots spécifiques ayant une signification particulière. En tant que tels, ils ne peuvent pas être utilisés par le développeur pour un rôle autre (par exemple comme nom de variable).

Liste des mots clefs Python 3 :
False, None, True, and, as, assert, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield.

Liste des mots clefs Python 2 :
and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield.

On peut remarquer que True, False et None ne sont pas des mots clefs dans Python 2. En effet, pour des raisons historiques, ces éléments n’étaient pas à l’origine inclus dans cette version. Ils ont ensuite été rajoutés plus tard, mais sous forme de variables internes à Python.

Ainsi, à l’exception de None protégé par un mécanisme spécifique, rien n’interdit, dans Python 2, de les réutiliser pour autre chose (aux risques du développeur bien évidemment).

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
# Exemple Python 2
>>> bool(True) == True
True
>>> True="Hello"                     # Pourquoi pas…
>>> bool(True) == True               # 1 est-il égal à "Hello" ?
False                                # Évidemment !!!

>>> None="Hello"
  File "<stdin>", line 1
SyntaxError: cannot assign to None

IV-10. Tout est objet

Python est un langage totalement objet. Et tous les types natifs mentionnés précédemment sont en réalité des types objets et possèdent donc des attributs (variables) et méthodes (actions) utilisables. Attributs et méthodes qui peuvent être visualisés avec la fonction native dir().

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
>>> x=5
>>> type(x)
<class 'int'>
>>> dir(x)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> x.bit_length
<built-in method bit_length of int object at 0x93b9890>
>>> x.bit_length()
3

De plus, les objets possèdent une mini documentation interne permettant de les décrire et d’expliquer les possibilités les concernant.

Cette documentation est accessible par la fonction help().

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
>>> x=5
>>> type(x)
<class 'int'>
>>> help(x)
Help on int object:

class int(object)
 |  int(x=0) -> int or long
 |  int(x, base=10) -> int or long
 | 
 |  Convert a number or string to an integer, or return 0 if no arguments
 |  are given.  If x is floating point, the conversion truncates towards zero.
 |  If x is outside the integer range, the function returns a long instead.
... (suite de la doc)…

L’aide est aussi disponible pour les méthodes de l’objet.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
>>> x=5
>>> type(x)
<class 'int'>
>>> help(x.bit_length)
Help on built-in function bit_length:

bit_length(...)
    int.bit_length() -> int
   
    Number of bits necessary to represent self in binary.
>>> bin(37)
    '0b100101'
>>> (37).bit_length()
    6
(END)

IV-11. La mutabilité

La mutabilité d’un objet se définit par la possibilité d’effectuer une opération appelée « hash » sur l’objet en question. Il s’agit d’une réduction mathématique représentant un élément de taille théoriquement illimitée (exemple une chaîne) en un nombre fini appelé souvent « somme de contrôle » ou « empreinte numérique ». Si l’opération est possible, on dit alors que l’objet est « hashable ».

Il existe divers algorithmes de hash (sha, md4, md5…). Même une simple action comme associer un fichier et sa taille est considérée comme une opération de hash du fichier.

Cette empreinte étant en quelque sorte une signature numérique de l’objet, en Python, elle doit lui correspondre à tout moment. Cette opération n’est donc possible que si l’objet est immuable.

Les chaînes de caractères et les nombres sont immuables. Des tuples seront immuables qu’à condition qu’ils ne contiennent eux‑mêmes que des objets immuables (si un tuple contient un objet mutable, de façon directe ou indirecte, il n’est pas immuable). Les listes, les ensembles ou les dictionnaires sont des objets naturellement modifiables donc non immuables. True, False et None sont immuables.

La mutabilité d’un objet aura des conséquences sur les façons de le copier (sera vu ultérieurement).


précédentsommairesuivant

Copyright © 2022 Svear (svear@free.fr) Permission est accordée de copier, distribuer ou modifier ce document selon les termes de la « Licence de Documentation Libre GNU » (GNU Free Documentation License), version 1.1 ou toute version ultérieure publiée par la Free Software Foundation.