Présentation de types simples¶
On verra dans cette page :
Python dispose de types de variables prédéfinis. On verra plus tard comment définir de nouveaux types qu'on appelle objets.
Il est possible de connaitre le type d'une variable en utilisant la fonction type()
:
a=3
print(type(a))
b=1+1j
print(type(b))
<class 'int'> <class 'complex'>
Notez qu'un type est plus qu'une facon de stocker une valeur. Il comprend aussi des fonctions qui permettent de le manipuler. Ces fonctions sont appelées méthodes dans la typologie des langages objets. Dans cette même typologie, les champs comme les valeurs réelle et imaginaire d'un complexe, sont appelés attributs.
Pour en savoir plus sur un type, on utilise help()
que l'on a déjà vu. Il existe aussi dir()
qui donne la liste brute des
méthodes et attributs. Regardons ce que nous dit l'aide sur b
:
help(b) # b est un complexe, donc help(b) affiche l'aide des nombres complexes
# cliquez dans la partie gauche du résultat pour réduire la cellule résultat
# double clic pour cacher la cellule résultat
Help on complex object: class complex(object) | complex(real=0, imag=0) | | Create a complex number from a real part and an optional imaginary part. | | This is equivalent to (real + imag*1j) where imag defaults to 0. | | Methods defined here: | | __abs__(self, /) | abs(self) | | __add__(self, value, /) | Return self+value. | | __bool__(self, /) | self != 0 | | __divmod__(self, value, /) | Return divmod(self, value). | | __eq__(self, value, /) | Return self==value. | | __float__(self, /) | float(self) | | __floordiv__(self, value, /) | Return self//value. | | __format__(...) | complex.__format__() -> str | | Convert to a string according to format_spec. | | __ge__(self, value, /) | Return self>=value. | | __getattribute__(self, name, /) | Return getattr(self, name). | | __getnewargs__(...) | | __gt__(self, value, /) | Return self>value. | | __hash__(self, /) | Return hash(self). | | __int__(self, /) | int(self) | | __le__(self, value, /) | Return self<=value. | | __lt__(self, value, /) | Return self<value. | | __mod__(self, value, /) | Return self%value. | | __mul__(self, value, /) | Return self*value. | | __ne__(self, value, /) | Return self!=value. | | __neg__(self, /) | -self | | __pos__(self, /) | +self | | __pow__(self, value, mod=None, /) | Return pow(self, value, mod). | | __radd__(self, value, /) | Return value+self. | | __rdivmod__(self, value, /) | Return divmod(value, self). | | __repr__(self, /) | Return repr(self). | | __rfloordiv__(self, value, /) | Return value//self. | | __rmod__(self, value, /) | Return value%self. | | __rmul__(self, value, /) | Return value*self. | | __rpow__(self, value, mod=None, /) | Return pow(value, self, mod). | | __rsub__(self, value, /) | Return value-self. | | __rtruediv__(self, value, /) | Return value/self. | | __sub__(self, value, /) | Return self-value. | | __truediv__(self, value, /) | Return self/value. | | conjugate(...) | complex.conjugate() -> complex | | Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j. | | ---------------------------------------------------------------------- | Static methods defined here: | | __new__(*args, **kwargs) from builtins.type | Create and return a new object. See help(type) for accurate signature. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | imag | the imaginary part of a complex number | | real | the real part of a complex number
Les méthodes ne s'utilisent pas comme les fonctions. Puisqu'elles sont rattachées à un type, on les attache à la variable sur laquelle on veut les appliquer avec un . en liaison :
b.conjugate() # et non conjugate(b) qui serait une fonction qui prend un complexe en argument
(1-1j)
On voit dans l'aide que presque toutes les méthodes commencent par __
comme __pow__
. Il s'agit de méthodes qui ne doivent pas être utilisées directement
mais qui sont reliées à des opérateurs ou à certains contextes comme l'indique l'aide. Ainsi __pow__
correspond à la puissance c.à.d. à l'opérateur **
:
print(b**2) # appelle en fait b.__pow__(2)
print(b.__pow__(2))
2j 2j
Les attributs s'appellent comme les méthodes mais n'étant que des champs, il n'y a pas de parenthèses :
b.real
1.0
Conversion d'un type vers un autre¶
Il est possible de changer le type d'une variable en choisissant explicitement le nouveau type :
x = 3
print(x, type(x))
x = float(x)
print(x, type (x))
y = complex(x)
print(y, type(y))
3 <class 'int'> 3.0 <class 'float'> (3+0j) <class 'complex'>
On notera que le type complexe a une méthode __int__
qui est justement celle utilisée pour transformer b
en un entier :
int(b)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-7-07ae29993d50> in <module> ----> 1 int(b) TypeError: can't convert complex to int
Cette méthode a été écrite pour générer une erreur avec un message explicite.
On a vu lors du cours sur les premiers calculs les types de base : entier, réel et complexe. Python offre d'autres types de base et l'écosystème de Python en offre encore plus.
Les chaînes de caractères¶
Python est particulièrement agréable pour manipuler des chaînes de caractères.
Une chaîne de caractères s'écrit entre deux doubles quotes "
ou deux simples quotes '
(on utilisera l'un si l'autre est présent dans la chaîne de caratères que l'on veut écrire).
prenom = 'Olivier'
print(prenom, len(prenom)) # len() pour length donne la taille d'une chaîne de caractères
surnom = prenom + ' ' + "l'Ancien" # + est la concaténation pour les chaîne de caractères
print("son surnom est", surnom)
Olivier 7 son surnom est Olivier l'Ancien
Il est possible d'inclure des valeurs dans une chaîne de caractère. Pour cela la méthode historique utilise une lettre clef en fonction du type de la valeur :
- `%s` pour les strings (chaînes de caractères),
- `%d` pour les digits (entiers),
- `%f` pour les floats (réels).
Ainsi "Bonjour %s, je vous attends depuis %d minutes" est une chaîne de caractère qui veut 2 arguments, un string et un digit.
phrase1 = "son prénom est %s, ce qui fait %d lettres" % (prenom, len(prenom))
print(phrase1)
son prénom est Olivier, ce qui fait 7 lettres
Un des attraits est la possibilité de formatage précis de l'affichage des valeurs :
print("1/3 sur 10 colonnes avec 5 chiffres après la virgule >%10.5f<" % (1./3))
print("La même chose mais aligné à gauche >%-10.5f<" % (1./3))
print("Comme premier mais avec des 0 à la place des espaces >%010.5f<" % (1./3))
print("%s = %.2E = %X en hexadécimal" % ('2 puissance 10', 2**10, 2**10))
1/3 sur 10 colonnes avec 5 chiffres après la virgule > 0.33333< La même chose mais aligné à gauche >0.33333 < Comme premier mais avec des 0 à la place des espaces >0000.33333< 2 puissance 10 = 1.02E+03 = 400 en hexadécimal
On regardera en détail dans le cours lesson2 Deeper in Python/03 - Formatting la signification précise de ces lignes cabalistiques ainsi que la nouvelle méthode d'insertion de valeurs dans une chaîne de caractère.
Manipulations¶
Parmi les fonctions utiles avec les chaînes de caractères, notons split
qui découpe la chaîne en mots avec le séparateur de notre choix (espace par défaut).
phrase = "Voila une jolie phrase que l'on va couper."
print(phrase.split()) # la valeur par défaut pour couper est l'espace
print(phrase.split('e'))
['Voila', 'une', 'jolie', 'phrase', 'que', "l'on", 'va', 'couper.'] ['Voila un', ' joli', ' phras', ' qu', " l'on va coup", 'r.']
Le résultat est une liste qui est justement le prochain type que l'on va regarder.
Les expressions régulières (re)¶
Pour aller plus loin avec les chaînes de caratères il faut utiliser les expressions régulières qui proviennent des fins fonds de l'informatique et que Python utilise comme tous les languages modernes.
Par exemple voici comment rechercher les mots qui comprennent a,e ou i suivi de deux l :
import re # la bibliothèque des regular expressions
blabla = "J'aime les filles rebelles qui jouent à la balle."
re.findall("\w*[a|e|i]ll\w*", blabla)
# c'est "\w*[a|e|i]ll\w*" qui est appelé expression regulière
['filles', 'rebelles', 'balle']
La maîtrise des expressions régulières n'est pas dans l'objet du cours mais il est bon de savoir qu'elles existent lorsqu'on doit faire des manipulations avancées sur des chaînes de caractères (pour savoir à quoi correspond \w
regardez ici).
Les listes¶
Une liste contient un ensemble de valeurs indexées. Une liste est définie entre crochets. Un liste vide est [ ].
a=[1,2,3,4,5,6,7,8]
print(a)
len(a) # len() pour length donne la taille d'une liste
[1, 2, 3, 4, 5, 6, 7, 8]
8
On peut avoir des listes de n'importe quoi, des listes de listes, des listes d'éléments hétérogènes :
b=[ ["Pomme", -21, "Banane"], ["euh", 5.34, 6.56+4j], 42]
len(b)
3
Pour savoir si un élément est dans une liste on utilise le mot clef in
:
print(42 in b)
print(-21 in b) # -21 is in the first element of b, not in b, it is not recursive
True False
Extraction¶
Extraire une valeur ou une sous-liste d'une liste se fait à l'aide des crochets et potentiellement 3 valeurs séparées par deux points :
[début : fin : indentation]
print("a[1] = ", a[1]) # le premier indice est 0
print("a[-1] = ", a[-1]) # -1 est le premier indice en partant de la fin (et non -0 :-)
print("a[2:4] = ", a[2:4]) # retourne une liste (le dernier élément est exclus)
print("a[3:-3] = ", a[3:-3])
print("a[5:] = ", a[5:]) # jusqu'à la fin
print("a[:-2] = ", a[:-2]) # depuis le début
print("a[::2] = ", a[::2]) # tous les 2 éléments !
print("a[1::2] = ", a[1::2])
print("a[::-1] = ", a[::-1]) # tous les élèments à l'envers
a[1] = 2 a[-1] = 8 a[2:4] = [3, 4] a[3:-3] = [4, 5] a[5:] = [6, 7, 8] a[:-2] = [1, 2, 3, 4, 5, 6] a[::2] = [1, 3, 5, 7] a[1::2] = [2, 4, 6, 8] a[::-1] = [8, 7, 6, 5, 4, 3, 2, 1]
Ajout et retrait¶
append
ajoute un élément en fin de liste. Cela permet de construire une liste en ajoutant les éléments un par un lorsque la construction de liste en compréhension n'est pas possible (cf chapitre suivant dans la partie sur les boucles).insert
insert un élement à la i-ème positionpop
retire l'élément à la i-ème position (et retourne sa valeur)remove
retire le premier élément qui vaut l'argument donné
On définit un tableau vide c ainsi c = []
. C'est utile pour pouvoir y ajouter des éléments par la suite.
c=[1,2,2,3]
c.append(8)
print(c)
c.insert(1, 33)
print(c)
c.pop(-1)
print(c)
c.remove(2)
print(c)
[1, 2, 2, 3, 8] [1, 33, 2, 2, 3, 8] [1, 33, 2, 2, 3] [1, 33, 2, 3]
Autres méthodes¶
index
permet de trouver une valeur, elle retourne la première position qui contient la valeurcount
permet de savoir combien de fois une valeur apparait dans la liste
c = [2, 4, 4, 2, 0]
print(c.index(4))
print(c.count(4))
1 2
sort
trie une listereverse
l'inverse
c.sort()
print(c)
c.reverse() # reverse est plus rapide que c[::-1]
print(c)
[0, 2, 2, 4, 4] [4, 4, 2, 2, 0]
Concaténation de listes¶
Les opérateurs + et * sur les listes font de la concaténation (on peut aussi utiliser extend
) :
c = [1,2,3,4]
print(c+c[2:])
print(3*c)
[1, 2, 3, 4, 3, 4] [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
Dans un cadre scientifique, on utilisera plutôt les tableaux (array
) de Numpy (on verra en détail Numpy plus tard). Pour les tableaux + et * sont les opérateurs mathématiques usuels et non de concaténation.
from numpy import array
d = array([1,2,3,4])
3*d
array([ 3, 6, 9, 12])
Une chaîne de caractères est une liste¶
a = "Patricia"
print(a[:3])
print(2*a)
print(a[::-1])
Pat PatriciaPatricia aicirtaP
Les dictionnaires¶
Le dictionnaire permet de stocker un mot clef et ce qui va avec (un mot et sa définition par exemple).
age = {"Pierre" : 23, "Jeanne" : 21, "Richard" : 20, "Sylvie" : 23, "Claire" : 24}
print(age["Sylvie"])
age['Pierre'] = 22 # change la valeur de Pierre
print(age['Pierre'])
23 22
Un dictionnaire n'a pas d'ordre. Ainsi vouloir le 3e élément n'a pas de sens tout comme le trier.
print(age)
print(len(age)) # par contre il a bien une longeur
{'Pierre': 22, 'Jeanne': 21, 'Richard': 20, 'Sylvie': 23, 'Claire': 24} 5
On ajoute ou retire un élément ainsi :
age['Olivier'] = 26 # attention, si Olivier existe, alors cela change sa valeur
print(age)
age.pop('Olivier')
print(age)
{'Pierre': 22, 'Jeanne': 21, 'Richard': 20, 'Sylvie': 23, 'Claire': 24, 'Olivier': 26} {'Pierre': 22, 'Jeanne': 21, 'Richard': 20, 'Sylvie': 23, 'Claire': 24}
On verra avec les boucles comment parcourir un dictionnaire.
Les n-uplets (tuples in english)¶
Les n-utplets sont des listes qu'on ne peut plus changer. Il s'agit donc de constantes, un concept utile car il offre la garantie que la variable a toujours la valeur initiale.
# on utilise les parenthèses pour définir les "tuples"
semaine = ('lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche')
semaine[0] = 'Monday'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-26-7563aee6d55c> in <module> 1 # on utilise les parenthèses pour définir les "tuples" 2 semaine = ('lundi','mardi','mercredi','jeudi','vendredi','samedi','dimanche') ----> 3 semaine[0] = 'Monday' TypeError: 'tuple' object does not support item assignment
week = list(semaine) # la conversion d'un type d'un objet en un autre s'effectue ainsi
print(week)
week[0]= 'Monday'
print(week)
['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche'] ['Monday', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']
Notons qu'il n'existe pas de constante en Python pour les variables contrairement à de nombreux autres langages. La convention veut qu'on écrive en majuscule les constantes afin de rendre visible le fait qu'il ne faut pas modifier cette variable.
{{ PreviousNext("01 - Les variables.ipynb","03 - Tests et boucles.ipynb") }}