2. Les types de données en Python¶
Il s’agit d’une introduction basique sur les types de données offerts par python. Cette introduction peut servir d’aide mémoire pour les utilisations les plus courantes, sachant que l’aide officiel de python est beaucoup plus complète.
2.1. Les nombres¶
C’est le type le plus simple. Il existe trois types de nombre :
Les entier (type
int
). Par exemplea = 5
, en binairea = 0b1001
, en hexadécimala = 0x23
.Les nombres à virgules flottante. Par exemple
a = 1234.234
oua = 6.2E-34
. Les nombres sont enregistré en double précision (64 bits). La précision relative est de 52 bits, soit environ \(10^{-16}\).:>>> a = 3.14 >>> a == a + 1E-15 False >>> a == a + 1E-16 True
Les nombres complexes. Il sont enregistrés sous la forme de deux nombres à virgules flottante. Par exemple
a = 1 + 3J
.
Les opérations sur les nombres sont les suivantes :
- somme :
+
- produit :
*
- différence ou négation :
-
- division :
/
- division entière :
//
- modulo :
%
(par exemple7%2
) - puissance :
**
(par exemple2**10
)
Avertissement
En Python 2, la division simple /
entre deux entiers est la division euclidienne. Ainsi, print 1/2
donne 0
.
Dans la version 3, la division simple renvoie toujours un flottant. Comme souvent, il est possible d’anticiper ce comportement
dans le dernière version de Python 2:
>>> from __future__ import division
>>> 1/2
0.5
Pour les nombres complexes, on peut facilement accéder à la partie réelle et imaginaire de la façon suivante : :
>>> a = 1 + 3J
>>> a.imag
3.0
>>> a.real
1.0
>>> print("Norme ", sqrt(a.real**2 + a.imag**2))
Norme 3.1622776601683795
Nous avons introduit ici des attributs d’objet. Il s’agit de la notation objet.attribut
(imag
est un attribut de l’objet 1 + 3J
). Nous verrons ceci plus en détail par la suite.
2.2. Les booléens et comparaison¶
Il existe deux valeurs : True
et False
(attention à la casse). Les opérations sont par ordre de priorité : not
, and
et or
. Les comparaisons se font à l’aide des symboles <
, <=
, ==
, >
et >=
. Pour savoir si deux valeurs sont différentes, on utilise <>
ou !=
.
Les symboles d’opérations que l’on a vu sont des opérateurs binaires, c’est a dire qu’il appellent implicitement une fonction prenant deux arguments. Ce n’est pas le cas de and et or qui effectue en fait un test conditionnel. L’instruction A and B
est interprété comme B if not A else A
, de même A or B
équivaut à A if A else B
. Voir le chapitre XXX pour cette syntaxe particulière.
Avertissement
Les symboles &
et |
sont des opérateurs binaires. Ils réalisent les opérations and et or sur les entiers bit par bit en binaire (par exemple 6 & 5
donne 4
). Il ne faut pas les utiliser pour les opérations sur des booléens.
2.3. Les chaînes de caractères (string)¶
2.3.1. Création d’une chaîne de caractères¶
Il existe trois façons de créer une chaîne de caractère : avec des
'
, des "
et des """
. Ces caractères servent à délimiter les
début et la fin du texte de la chaîne de caractère. Les guillemets
simples '
et doubles "
sont équivalents. On pourra choisir l’un ou
l’autre. Il sera cependant judicieux, si une chaîne de caractère doit contenir
un de ces guillements, d’utiliser l’autre pour le début et la fin de la chaîne.
Les trois guillements sont eux utilisés lorsque l’on veut qu’une chaîne
de caractère soit sur plusieurs lignes.
Voici quelques exemples :
>>> s = 'Pierre'
>>> s = "Aujourd'hui" #Rq : s = 'Aujourd'hui' ne va pas fonctionner
>>> s = """Aujourd'hui, le petit enfant a dit:
... "Faisons le clown!" """
2.3.2. Caractères spéciaux¶
Les caractères spéciaux sont les caractères qui ne sont pas affichables et en tant que tel.
Par exemple, il existe un caractère pour le retour à la ligne. Il est possible
d’utiliser ce caractère dans une chaîne en utilisant \n
. L’antislash sert
ici de caractère d’échappement pour indiquer que l’on va entrer un caractère
spécial. La lettre n
indique ici qu’il s’agit d’un retour à la ligne.
Voici un exemple :
>>> s = "Un\nDeux"
>>> print(s)
Un
Deux
>>> len(s) # \n compte pour un caractère
7
L’antislash sert aussi à insérer un guillemet dans une chaîne : 'Aujourd\'hui'
.
2.3.3. Manipulation des chaînes de caractères¶
Tout comme une liste, il est possible d’accéder à chaque caractère d’une chaîne ou à une partie d’une chaîne.
>>> s = "Pierre"
>>> s[0]
'P'
>>> s[1:3]
'ie'
La longueur de la chaîne s’obtient avec la fonction len
. On peut aussi faire une boucle for
sur chacun des éléments de la chaîne.
Cependant, il n’est pas possible de modifier une chaîne de caractères (l’opération s[0]='p'
échoue).
La concaténation est l’opération qui consiste à créer une nouvelle chaîne en
mettant à la suite deux chaînes de caractères. Elle se fait à l’aide
du signe +
. Par exemple :
>>> s1 = 'Un'
>>> s2 = 'Deux'
>>> s1+s2
'UnDeux'
Une autre opération est importante, il s’agit du formatage d’une chaîne de caractère. Cette opération consiste à insérer un élément variable dans une chaîne. Elle est souvent utilisée lorsque l’on veut afficher proprement un résultat. Voici une exemple :
>>> heure = 15
>>> minute = 30
>>> "Il est {0}h{1}".format(heure, minute)
'Il est 15h30'
Pour insérer un élément ou plusieurs éléments variables
dans une chaîne de caractère, on crée d’abord cette chaîne en mettant à la
place des ces éléments une accolade avec un numéro d’ordre {i}
. En appliquant la
méthode format
sur cette chaîne, les accolades seront remplacées par
le ième argument.
2.3.4. Formatage de nombre¶
Nous avons déjà vu qu’il était possible de transformer un nombre en une chaîne de caractère à l’aide de la fonction str
. En utilisant le formatage de chaîne de caractère, il est possible de spécifier en détail comment ce nombre doit s’afficher. Par exemple, si il s’agit d’un nombre à virgule flottante, combien de décimales faut-il afficher, faut il utiliser la notation scientifique, etc. Pour cela, on rajoute à l’intérieur des accolades un code particulier. Ce code est précédé du signe ‘:’.
Voici quelques exemples :
>>> from math import pi
>>> '{0:.5f}'.format(pi)
'3.14159'
>>> c = 299792458. # Vitesse de la lumière en m/s
>>> 'c = {0:.3e} m/s'.format(c)
'c = 2.998e+08 m/s'
Le ‘f’ indique que l’on veut une notation a virgule fixe, le ‘e’ une notation scientifique. Le chiffre que l’on indique après le ‘.’ donne le nombre de chiffre après la virgule que l’on souhaite.
Note
L’aide en ligne de Python fournit d’autres exemples et des détails.
Il existe aussi une façon plus élémentaire de formater des chaîne de caractères avec Python et qui est obsolète (mais que l’on peut rencontrer). Pour formater le nombre pi
, cette méthode écrira dans ce cas '%.6f'%pi
.
2.3.5. Les accents¶
Historiquement, l’informatique étant née dans des pays anglo-saxons, les caractères utilisés se limitent aux caractères latin simple (sans accent). En utilisant les lettre minuscules, majuscules, les chiffres et autres signes, une norme est apparu concernant 128 caractères. Chaque caractère se voyant attribué un nombre entre 0 et 127 (\(2^7\)). Dans un fichier informatique, chaque caractère correspond alors à un octet. Les 128 octets restant ont fait l’objet de normes locales (par exemple la norme Windows-1252 pour les ordinateurs vendu dans le pays latins occidentaux, ISO 8859-1 pour les unix/linux).
Un nouveau standard, l’unicode a été développé à partir des années 90. Ce standard associe un nombre unique à chaque caractère (dans plus de 90 langues), allant des hiéroglyphes égyptiens aux milliers de sinogrammes asiatiques. Reste alors le problème d’enregistrer dans un fichier un texte écrit à l’aide de cette norme. Le plus simple serait, au lieu d’utiliser un octet par caractère, d’utiliser plusieurs octets. Cependant, les fichiers contenant du texte simple seraient alors inutilement long. Et d’autre part, il n’y aurait pas de compatibilité vers le standard ASCII (un fichier ASCII serait mal interprété). Il existe une norme permettant de ne pas avoir ces inconvénients : il s’agit de l’UTF-8. Les caractères ASCII standard dont toujours enregistré sur un octet, et on utilise plusieurs octets pour les autres caractères.
Dans Python 3, que nous utilisons, les chaînes de caractères sont des chaînes de caractères unicode. Si on souhaite des chaînes d’octet ASCII, il faut alors préfixer la chaîne par une b
, par exemple b'abcde'
. Dans Python 2, le comportement est opposé, par défaut les chaînes sont des chaînes d’octet et pour créer une chaîne unicode, il faut préfixer par un u
.
Il est possible de rentrer un caractère directement à partir de sa
valeur unicode. Il y a deux façons : pour un simple caractère, on peut
utiliser la fonction chr
(unichr en Python 2), pour un caractères dans une chaîne on
utilise la séquence suivante '\uxxxx'
, où xxxx
est la valeur
en hexadécimal du caractère unicode.
Par exemple, la lettre grec α (alpha) a pour valeur 945. En héxadécimal, elle s’écrit 03B1. On pourra l’utiliser de la façon suivante :
>>> chr(945)
'α'
>>> print("La lettre \u03B1 est la première lettre de l'alphabet grec")
La lettre α est la première lettre de l'alphabet grec
Il y a enfin une notion supplémentaire qu’il faut introduire, il s’agit
de la possibilité d’afficher ou non un caractère. La console que nous
utilisons (sous linux ou spyder) permet d’afficher un très grand nombre de
caractères (essayer par exemple print u'\u4e2d\u570b'
ou print
u'\u0646\u0627\u0646\u0628\u0644'
). Elle ne permet cependant pas
d’afficher les hiéroglyphes... Beaucoup de logiciels
utilisent des polices de caractères qui n’affichent qu’une
partie très restreinte de la table unicode.
2.4. Les listes (list)¶
On peut créer et remplir une liste de plusieurs manières :
>>> l = [1, 2, 3, 4] >>> l = [] # liste vide >>> l.append(3) >>> l [3] >>> l.append(4) >>> l [3, 4] >>> l.insert(0,3.24+1j) >>> l [(3.24+1j), 3, 4] >>> len(l) # Longueur de la liste 3
On peut changer un élément de la liste :
>>> l[2] = 23
On peut créer une nouvelle liste à partir d’une liste à l’aide de la commande
list
:>>> l = [2, 3] >>> m = list(l) >>> l.append(45) >>> l==m False
La commande
range(n)
peut être utilisée pour créer la liste[0,1,2, .., n-2, n-1]
. Cette liste commence à0
et contientn
nombres (elle s’arrête donc àn-1
).>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Techniquement, depuis la version 3 de Python, range ne renvoie plus une liste, mais un générateur. Ce générateur produit la suite de chiffre qui est ensuite utilsée par le constructeur de la liste.
Une liste peut contenir des éléments de types différents.
Souvent on a besoin de créer une liste dans une boucle. Par exemple la liste des
n
premiers nombres au carré peut se calculer de la façon suivantel = [] for i in range(n): l.append(i**2)
Il existe cependant une façon plus directe de faire, en utilisant les
list comprehension
l = [i**2 for i in range(n)]
Cette syntaxe se lit directement en français : calcule la liste des i au carré pour i allant de 0 à n. Il est aussi possible de rajouter une condition ( pour i allant de 0 à n si i est pair )
l = [i**2 for i in range(n) if i%2==0]
Si on souhaite appliquer une fonction à tous les éléments d’une liste pour recréer une liste, il est possible d’utiliser la fonction
map
def mafonction(i): if i%2==0: return i**2 else: return i**2-1 map(mafonction, range(5)) # [0,0,4,8,16]
On peut parcourir une liste de plusieurs façons
l = [1, 3, 5, "Pierre"] for elm in l: print(elm) for i,elm in enumerate(l): print(elm, " est l'element numero ",i," de la liste)
Avec les listes, nous avons donc introduit la structure de contrôle for
. Celle ci fonctionne sur tout type de séquence (par exemple les chaînes de caractères). Par cette syntaxe, elle est assez différente de ce qui existe dans d’autres langage informatique.
Note
Nous avons vu qu’il était possible de rajouter des éléments dans une liste. Pour cela, nous avons utilisé la syntaxe l.append(elm)
. Il s’agit ici de programmation orientée objet. Il est utile de savoir reconnaître la syntaxe : la liste est suivi du nom de la fonction que l’on applique (on appelle cette fonction une méthode) avec ses arguments. Ici, donc, append
rajoute elm
à la liste l
.
Notons de plus, que l’objet l
est modifié. La variable l
désigne toujours la même liste, mais cette liste est modifiée (si on ajoute une page à un classeur, il s’agit toujours du même classeur). Ce comportement est différent de celui que nous avons vu dans la paragraphe précédent avec la méthode format
sur les chaînes de caractères. En effet dans ce cas, on crée un nouvelle chaîne de caractère qui est renvoyé par la méthode - la chaîne initiale n’étant pas modifiée. La méthode append
appliquée à une liste, modifie la liste, mais ne renvoie rien.
Pour trier une liste, on peut soit utiliser la méthode
.sort
qui modifie la liste soit la fonction sorted qui renvoie une nouvelle liste triée. Il est possible d’ajouter comme argument optionnel une fonction qui donne l’ordre. Par defaut, python utilise la fonction cmp (ordre croissant pour les nombre et alphabétique pour le chaîne)l = ['Pour', 'trier', 'une', 'liste', 'on', 'peut'] print(sorted(l)) def compare(a,b): u""" Ordre alphabétique inversé sans tenir compte de la casse""" return cmp(b.lower(), a.lower()) sorted(l, compare)
Fonction
zip
: lorsque l’on veut parcourir deux listes en même temps, il est possible d’utiliser la fonction zip qui crée alors une liste de n-uplets à partir den
listes. :>>> liste_nom = ['Martin', 'Lefevre', 'Dubois', 'Durand'] >>> liste_prenom = ['Emma', 'Nathan', 'Lola', 'Lucas']
>>> for nom, prenom in zip(liste_nom, liste_prenom): ... print(prenom, nom) Emma Martin Nathan Lefevre Lola Dubois Lucas Durand
2.5. Les n-uplets (tuple)¶
Les n-uplets sont utilisés lorsque l’on veut regrouper des valeurs ensembles. On utilise une liste lorsque l’on a une longue séquence (dont la longueur est souvent variable) et un n-uplet pour regrouper quelques éléments. Par exemple :
>>> personne = ('Jean', 'Dupont', '13 juillet 1973', 38)
>>> print('Nom :',personne[1])
Nom : Dupont
Les n-uplets sont utilisés lorsqu’une fonction renvoie plusieurs éléments :
>>> def fonction(x):
... return x**2,x**3
>>> a = fonction(4)
>>> a
(16, 64)
>>> a,b = fonction(4)
2.6. Les dictionnaires (dictionnary)¶
Contrairement aux listes ou aux n-uplets qui sont indéxés par des
nombres (l[2]
), un dictionnaire est indéxé par une clé. En
général, la clé est une chaîne de caractère ou un nombre. On peut
reprendre l’exemple précédent :
>>> personne = {"Prenom":"Jean", "Nom":"Dupont",
... "date_naissance":"13 juillet 1973", "Age":38}
>>> print("Nom :",personne['Nom'])
Nom : Dupont
Tout comme pour une liste, on peut ajouter ou enlever des éléments à un dictionnaire :
>>> personne['telephone'] = "02 99 79 24 58"
>>> del personne['Age']
Il est possible de parcourir et accéder à un dictionnaire de plusieurs façons :
>>> releve_note = {'Jacques':15, 'Jean':16, 'Pierre':14}
# Par clef
>>> for nom in sorted(releve_note.keys()):
... print('La note de {0} est {1}'.format(nom, releve_note[nom]))
La note de Jacques est 15
La note de Jean est 16
La note de Pierre est 14
# Par valeurs
>>> notes = releve_note.values()
>>> print("Moyenne", sum(notes)/len(notes))
Moyenne 15.0
# Par clef et valeur
>>> for cle, val in releve_note.items():
... print('La note de {0} est {1}'.format(cle, val))
La note de Pierre est 14
La note de Jean est 16
La note de Jacques est 15
La clé d’un dictionnaire doit être un objet non modifiable, c’est à dire un nombre, une chaîne de caractère ou un tuple contenant uniquement des objets non modifiables.
2.7. Les ensembles (set)¶
Utilisé pour représenter un ensemble non-ordonné d’éléments qui sont tous différents. Par exemple :
>>> a = set([1,2,3])
>>> b = set([3,5,6])
>>> c = a | b # union
>>> d = a & b # intersection
Un exemple d’application :
>>> mdp = raw_input('Entrez un mot de passe contenant \
... au moins un signe de ponctuation')
>>> ponctuation = set("?,.;:!")
>>> if (ponctuation & mdp == set()):
... print("Le mot de passe ne contient pas de signe de ponctuation")
Les ensembles sont très pratiques lorsque l’on veut supprimer des doublons.
Exercice
Récupérez un texte quelconque en chinois (par exemple https://www.gutenberg.org/files/24051/24051-0.txt). Combien d’idéogrammes chinois différents sont utilisés dans ce texte?
2.8. Tableaux numpy (numpy array)¶
Cette structure n’est pas native de Python, mais fait partie du package numpy. C’est la structure qu’il faut utiliser pour traiter des données ou faire des calculs numériques. A la différence d’une liste, la taille d’un tableau numpy n’est pas modifiable et l’ensemble des données doit être du même type. Ces conditions permettent un traitement beaucoup plus rapide des données. Cette structure sera vue en détail dans la partie dédiée à numpy.
Quelques exemples :
>>> import numpy as np
>>> a = np.array([[1.5,3.14,5.27],[2.17,0.69,1.414]])
>>> a.shape
(2, 3)
>>> print(a.dtype)
float64
>>> print(a[1,2]) # Attention, notation en partant de 0, comme en C
... # mais pas comme en Fortran, scilab, matlab, ...
1.414
>>> a[1,2] = 8.56 # on peut changer un element
>>> a = np.arange(5) # comme range, sauf que l'on renvoie un tableau
a = np.loadtxt('data_file.txt')
# data_file est une fichier texte contenant des
# données numériques (type tableur)
Un grand nombre d’opération simple peut être réalisé sur des tableaux. Elle sont réalisées élément par élément :
>>> a = np.array([[1.5,3.14,5.27],[2.17,0.69,1.414]])
>>> b = 2*a + a**2 - a
Important : lors de l’utilisation de tableau contenant un grand nombre de données, cette méthode est beaucoup plus rapide (en plus d’être plus simple) que de faire l’opération élément par élément avec une liste. A titre d’exemple comparer la vitesse de
# N premiers carrés
a = [i**2 for i in range(1000000)]
b = np.arange(1000000)**2
Les tableaux numpy sont proche du C ou de Fortran. Ils offrent plus de type que Python. Par exemple les nombres à virgule flottante peuvent être enregistrés en 32, 64 ou 96 bits.
Avertissement
Attention, le type des éléments d’un tableau ne peut pas être modifié. Ainsi, si un tableau est défini comme un tableau d’entier, on ne peut pas mettre dedans un nombre flottant. Celui ci sera automatiquement converti en nombre entier. C’est un piège auquel il faut faire attention
>>> a = np.arange(5)
>>> a[1] = 3.141592
>>> a[1]
3