Comme tout langage, Python permet de manipuler des données grâce à un vocabulaire de mots réservés et grâce à des types de données - approximation des ensembles définis en mathématique.
Ce chapitre présente les règles de construction des identifiants, les types de données simples (les conteneurs seront examinés au chapitre Les conteneurs standard) ainsi que les types chaîne de caractères (Unicode et binaires).
Enfin, last but not the least, ce chapitre s’étend sur les notions non triviales de variables, de références d’objet et d’affectation.
La boucle d’évaluation de IDLE
Comme tout langage, Python utilise un identifiant pour nommer chaque objet.
Sachant que :
Note
En python 2.6, les caractères ne peuvent être que des lettres ASCII, c’est à dire sans accent
Warning
Les identifiants sont sensibles à la casse et ne doivent pas être un mot clé.
Astuce
Pour être certain de ne pas empiéter sur le vocabulaire (mot clés et bibliothèque standard de Python), essayez ceci en mode interactif :
>>> # Un symbole valable doit produire les erreurs suivantes
>>> symbole
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'symbole' is not defined
>>> import symbole
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named symbole
>>> # Un symbole non valable doit produire Une erreur de syntaxe
>>> with
File "<stdin>", line 1
with
^
SyntaxError: invalid syntax
>>> # Un import de symbole non valable ne produit pas d'erreur
>>> import calendar
Il est important d’utiliser une politique cohérente de nommage des identifiants.
Voici les styles préconisés :
Exemples :
NB_ITEMS = 12 # UPPER_CASE
class MaClasse: pass # TitleCase
def maFonction(): pass # camelCase
mon_id = 5 # lower_case
La version 3.1.1 de Python compte 33 mots clés :
|
|
|
|
| [1] | N’est pas supporté par Python 2.x. |
| [2] | N’est supporté que par Python 2.x en tant que mot clé. |
Exemples de deux expressions simples et d’une expression complexe :
id1 = 15.3
id2 = maFonction(id1)
if id2 > 0:
id3 = math.sqrt(id2)
else:
id4 = id1 - 5.5*id2
Python 3 offre deux types entiers standard : int et bool.
Le type int n’est limité en taille que par la mémoire de la machine.
Les entiers littéraux sont décimaux par défaut, mais on peut aussi utiliser les bases suivantes :
>>> 2009 # décimal
2009
>>> 0b11111011001 # binaire
2009
>>> 0o3731 # octal
2009
>>> 0x7d9 # hexadecimal
2009
Opérations arithmétiques
Les principales opérations :
>>> 20 + 3
23
>>> 20 - 3
17
>>> 20 * 3
60
>>> 20 ** 3
8000
>>> 20 / 3
6.666666666666667
>>> 20 // 3 # division entière
6
>>> 20 % 3 # modulo
2
>>> abs(3 - 20) # valeur absolue
17
Bien remarquer le rôle des deux opérateurs de division :
Note
En python 2.6, les nombres dépassants 2 puissance 63 - 1 étaient des long. La notation des longs est marquée par un L ex : 9223372036854775808L
>>> 2 > 8
False
>>> 2 <= 8 < 15
True
Opérateurs logiques (concept de shortcut) : not, or et and.
En observant les tables de vérité des opérateurs and et or (cf. p. 108), on remarque que :
- dès qu’un premier membre à la valeur False, l’expression False and expression2 vaudra False. On n’a donc pas besoin de l’évaluer ;
- de même dès qu’un premier membre à la valeur True, l’expression True or expression2 vaudra True.
Cette optimisation est appelée “principe du shortcut” :
>>> (3 == 3) or (9 > 24) # True (dès le premier membre)
True
>>> (9 > 24) and (3 == 3) # False (dès le premier membre)
False
Les expressions booléennes
Une expression booléenne a deux valeurs possibles : False ou True.
Python attribut à une expression booléennes la valeur False si c’est :
Tout le reste vaut True.
Exemple :
>>> l = ( None, "N'est pas False", "", (), (1), [], [1] , {}, {'a':'A'},
... True, False, 0, 1)
>>> for e in l:
... print("{!r} est {}".format(e, e and "VRAI" or "FAUX"))
...
None est FAUX
"N'est pas False" est VRAI
'' est FAUX
() est FAUX
1 est VRAI
[] est FAUX
[1] est VRAI
{} est FAUX
{'a': 'A'} est VRAI
True est VRAI
False est FAUX
0 est FAUX
1 est VRAI
>>> float()
0.0
>>> float(1) # Construit avec un entier = conversion
1.0
>>> 2.718
2.718
>>> .02
0.02
>>> 3e8
300000000.0
>>> 6.023e23
6.0229999999999998e+23
>>> import math
>>> math.sin(math.pi/4)
0.70710678118654746
>>> math.degrees(math.pi)
180.0
>>> math.factorial(9)
362880
>>> math.log(1024, 2)
10.0
>>> 1j
1j
>>> (2+3j) + (4-7j)
(6-4j)
>>> (9+5j).real
9.0
>>> (9+5j).imag
5.0
>>> abs(3+4j)
5.0
>>> import cmath
>>> cmath.phase(-1 + 0j)
3.1415926535897931
>>> cmath.polar(3 + 4j)
(5.0, 0.92729521800161219)
>>> cmath.rect(1., cmath.pi/4)
(0.70710678118654757+0.70710678118654746j)
Dès que l’on possède des types de données, on a besoin des variables pour stocker les données.
En réalité, Python n’offre pas la notion de variable, mais plutôt celle de référence d’objet. Tant que l’objet n’est pas modifiable (comme les entiers, les flottants, etc.), il n’y a pas de différence notable. On verra que la situation change dans le cas des objets modifiables...
La valeur d’une variable, comme son nom l’indique, peut évoluer au cours de chaque affectation (la valeur antérieure est perdue) :
>>> a = a + 1 # 3 (incrémentation)
>>> a = a - 1 # 2 (décrémentation)
Affectation
L’ affectation a un effet (elle modifie l’état interne du programme en cours d’exécution) mais n’a pas de valeur (on ne peut pas l’utiliser dans une expression) :
>>> a = 2
>>> x = (a = 3) + 2
SyntaxError: invalid syntax
Comparaison
La comparaison a une valeur utilisable dans une expression mais n’a pas d’effet (l’automate interne représentant l’évolution du programme n’est pas modifié) :
>>> x = (a == 3) + 2
>>> x
2
Outre l’affectation simple, on peut aussi utiliser les formes suivantes :
# affectation simple
v = 4
# affectation augmentée
v += 2 # idem à : v = v + 2 si v est déjà référencé
# affectation de droite à gauche
c = d = 8 # cibles multiples
# affectations parallèles d'une séquence
e, f = 2.7, 5.1 # tuple
g, h, i = ['G', 'H', 'I'] # liste
x, y = coordonneesSouris() # retour multiple d'une fonction
Dans les schémas des figures ci-dessous, les cercles représentent les identificateurs alors que les rectangles représentent les données.
Les affectations relient les identificateurs aux données : si une donnée en mémoire n’est plus reliée, le ramasse-miettes (garbage collector) de Python la supprime automatiquement :
Exemple (a) : Trois affectations
Exemple (b) : La donnée ‘c’ est supprimée
Exemple (c) : La donnée ‘a’ est supprimée
Trois syntaxes de chaînes sont disponibles.
Remarquez que l’on peut aussi utiliser le ‘ à la place de “, ce qui permet d’inclure une notation dans l’autre :
syntaxe1 = "Première forme avec un retour à la ligne \n"
syntaxe2 = r"Deuxième forme sans retour à la ligne \n"
syntaxe3 = """
Troisième forme multi-ligne
"""
guillemets = "L'eau vive"
apostrophes = 'Forme "avec des apostrophes"'
Note
En python 2.6 “une chaine” est en faite une suite d’octets, contrairement à la chaîne unicode u”Avec un é” qui correspond à la chaine de caractères de python 3.
Il faut passer de la chaine d’octets vers l’unicode en utilisant la méthode decode et en précisant l’encodage exemple :
>>> print "Le \xc3\xa9 en utf8 est cod\xc3\xa9 sur 2 octets".decode("utf-8")
Le é en utf8 est codé sur 2 octets
>>> print "Le \xe9 en iso 8859-15 est cod\xe9 sur 1 octet".decode("iso 8859-15")
Le é en iso 8859-15 est codé sur 1 octet
Pour passer d’un encodage à un autre directement depuis une chaine d’octets, on utilise la méthode encode en lui précisant en paramètre l’encodage de destination et l’encodage source :
>>> 'le symbole euro \xe2\x82\xac'.encode("iso 8859-15", "utf8")
'le symbole euro \xa4'
Attention
Un caractère unicode occupe 4 octets en mémoire, il s’agit d’un chiffre dont la valeur numérique correspond au symbole a représenter. Ainsi le é a pour valeur 233 (e9) soit en mémoire “00 00 00 E9”, or en iso 8859-15 le é a aussi pour valeur 233 (e9), mais en mémoire il prendra simplement un octet soit “E9”.
Beaucoup d’erreurs de compréhension viennent de cette intersection dans la représentation des unicodes et des iso 8859-15.
>>> s = "abcde"
>>> len(s)
5
>>> s1 = "abc"
>>> s2 = "defg"
>>> s3 = s1 + s2
>>> s3
abcdefg
>>> s4 = "Fi! "
>>> s5 = s4 * 3
>>> s5
Fi! Fi! Fi!
On peut agir sur une chaîne (et plus généralement sur une séquence) en utilisant des fonctions (notion procédurale) ou des méthodes (notion objet).
>>> ch1 = "abc"
>>> long = len(ch1)
3
>>> ch2 = "abracadabra"
>>> ch3 = ch2.upper()
ABRACADABRA
Les méthodes suivantes sont à valeur booléennes, c’est-à-dire qu’elles retournent la valeur True ou False.
La notation [xxx] indique un élément optionnel que l’on peut donc omettre lors de l’utilisation de la méthode.
>>> print("cHAise basSe".isupper())
False
>>> print("Chaise Basse".istitle())
True
>>> print("3 chaises basses".isalpha())
False
>>> print("54762".isdigit())
True
>>> print("abracadabra".startswith('ab'))
True
>>> print("abracadabra".endswith('ara'))
False
>>> # s sera notre chaîne de test pour toutes les méthodes
>>> s = "cHAise basSe"
>>> print(s.lower())
chaise basse
>>> print(s.upper())
CHAISE BASSE
>>> print(s.capitalize())
Chaise basse
>>> print(s.swapcase())
ChaISE BASsE
>>> print(s.center(20, '-'))
----cHAise basSe----
>>> print(s.rjust(20, '@'))
@@@@@@@@cHAise basSe
>>> print(s.zfill(20))
00000000cHAise basSe
>>> print(s.strip('ce'))
HAise basS
>>> print(s.find('se b'))
4
>>> print(s.replace('HA', 'ha'))
chaise basSe
>>> print(s.split())
['cHAise', 'basSe']
>>> print("**".join(['cHAise', 'basSe']))
cHAise**basSe
Pour indicer une chaîne, on utilise l’opérateur [x] dans lequel l’indice x, un entier signé qui commence à 0 indique la position d’un caractère :
>>> s = "Rayon X"
>>> len(s)
7
>>> print(s[0])
R
>>>>> print(s[2])
y
>>> print(s[-1])
X
>>> print(s[-3])
n
L’indiçage d’une chaîne
L’opérateur [ ] avec 2 ou 3 indices séparés par le caractère permet d’extraire des sous-chaînes (ou tranches) d’une chaîne. La littérrature anglophone appelle cette notation le “slice” :
>>> s = "Rayon X"
>>> len(s)
7
>>> s[1:4] # (de l'indice 1 compris à 4 non compris)
'ayo'
>>> s[-2:] # (de l'indice -2 compris à la fin)
' X'
>>> s[:3] # (du début à 3 non compris)
'Ray'
>>> s[3:] # (de l'indice 3 compris à la fin)
'on X'
>>> s[::2] # (du début à la fin, de 2 en 2)
'RynX'
L’extraction de sous-chaînes.
Une donnée binaire contient une suite de zéro ou plusieurs octets, c’est-à-dire d’entiers non-signés sur 8 bits (compris dans l’intervalle [0...255]). Ces types à la C sont bien adaptés pour stocker de grandes quantités de données. De plus Python fournit des moyens de manipulation efficaces de ces types.
Les deux types sont assez semblables au type str et possèdent la plupart de ses méthodes. Le type modifiable bytearray possède des méthodes communes au type list.
Exemples de données binaires et de méthodes :
>>> b_mot = b"Animal" # chaîne préfixée par b : type byte
>>> print(b_mot)
b'Animal'
>>> for b in b_mot:
... print(b, end=" ") # (cf. table ASCII)
...
65 110 105 109 97 108
>>> bMot = bytearray(b_mot) # retourne un nouveau tableau de bytes...
>>> bMot.pop() # ...qui possède les méthodes usuelles
108
>>> bMot
bytearray(b'Anima')
>>> data = b"5 Hills \x35\x20\x48\x69\x6C\x6C\x73"
>>> data.upper()
b'5 HILLS 5 HILLS'
>>> data.replace(b"ill", b"at")
b'5 Hats 5 Hats'
Bien différencier les codes, glyphes, caractères et octets !
Codes, glyphes, caractères et octets.
L’utilisateur à besoin d’interagir avec le programme. En mode “console”, on doit pouvoir saisir ou entrer des informations, ce qui est généralement fait depuis une lecture au clavier. Inversement, on doit pouvoir afficher ou sortir des informations, ce qui correspond généralement à une écriture sur l’écran.
Les entrées-sorties.
Il s’agit de réaliser une saisie à l’écran : la fonction standard input() interrompt le programme, afficher une éventuelle invite et attend que l’utilisateur entre une donnée et la valide par Entrée. La fonction standard input() effectue toujours une saisie en mode texte (la saisie est une chaîne) dont on peut ensuite changer le type (on dit aussi transtyper) :
>>> nb_etudiant = input("Entrez le nombre d'étudiants : ")
>>> type(nb_etudiant) # (c'est une chaîne)
<class 'str'>
>>> f1 = input("\nEntrez un flottant : ")
>>> f1 = float(f1) # transtypage en flottant
>>> # ou plus brièvement :
>>> f2 = float(input("Entrez un autre flottant : "))
>>> type(f2))
<class 'float'>
En mode “Console”, Python lit-évalue-affiche, mais la fonction print() reste indispensable aux affichages dans les scripts :
>>> import sys
>>> a, b = 2, 5
>>> print(a, b)
2 5
>>> print("Somme :", a + b)
Somme : 7
>>> print(a - b, "est la différence")
-3 est la différence
>>> print("Le produit de", a, "par", b, "vaut :", a * b)
Le produit de 2 par 5 vaut : 10
>>> print() # affiche une nouvelle ligne
>>> # pour afficher un espace à la place de la nouvelle ligne:
>>> print(a, end=" ")
2 # (et ne va pas à la ligne)
>>> print("\nErreur fatale !", file=sys.stderr) # dans un fichier
>>> print("On a <", 2**32, "> cas !", sep="###")
On a <###4294967296###> cas !
Attention
La fonction print n’est pas active par défaut en Python 2.6. Voir la note à cette adresse : http://docs.python.org/library/functions.html#print
À l’intérieur d’une chaîne, le caractère antislash \ permet de donner une signification spéciale à certaines séquences :
| Séquence | Signification |
| \ | saut_ligne saut de ligne ignoré |
| \\ | affiche un antislash |
| \' | apostrophe |
| \" | guillemet |
| \a | sonnerie (bip) |
| \b | retour arrière |
| \f | saut de page |
| \n | saut de ligne |
| \r | retour en début de ligne |
| \t | tabulation horizontale |
| \v | tabulation verticale |
| \Nnom | caractère sous forme de code Unicode nommé |
| \uhhhh | caractère sous forme de code Unicode 16 bits |
| \Uhhhhhhhh | caractère sous forme de code Unicode 32 bits |
| \ooo | caractère sous forme de code octal |
| \xhh | caractère sous forme de code hexadécimal |
Exemples :
>>> print("\N{pound sign} \u00A3 \U000000A3")
£ £ £
>>> print("d \144 \x64")
d d d
>>> print("d \144 \x64") #séquence d'échapement inactive dans les chaînes brutes
d \144 \x64