Python3 : des fondamentaux à l’utilisation du langage
les concepts majeurs de python¶
tout est un objet
objets mutables ou non
références partagées
liaison statique
itérateurs
espaces de nommage
modèle mental : tout est objet¶
%load_ext ipythontutor%%ipythontutor heapPrimitives=true height=500 width=800 curInstr=2
a = 1
b = "ma chaine"
liste = [1, 10., 10 + 10j]
import math
def foo(x):
return 2 * xmodèle mental : tout objet est typé¶
# créons quelques objets
a = 1
b = "ma chaine"
liste = [1, 10., 10 + 10j]# et définissons une fonction
# en fait c'est un objet aussi !
def foo(x):
return x * 2
# et le module aussi !
import math# a désigne un entier
# b désigne une chaine
type(a), type(b)(int, str)# une liste
type(liste)list# un complexe
# (les indices commencent à 0)
type(liste[2])complex# un module
type(math)module# une fonction
type(foo)functionmodèle mental : objets mutables¶
selon leur type, les objets sont
modifiables : mutables
ou pas : immutables (on dit aussi parfois immuables)
par exemple: une liste est mutable...
%%ipythontutor heapPrimitives=true
# je peux MODIFIER la liste
liste1 = [1, 2, 3]
liste1[1] = 100modèle mental : objets non mutables¶
par contre, une chaine est non mutable ou immutable
# je ne PEUX PAS modifier la chaine !
chaine = 'abc'
try:
chaine[1] = 'z'
except Exception as exc:
print("BOOM !", exc, " -- ", type(exc))BOOM ! 'str' object does not support item assignment -- <class 'TypeError'>
modèle mental: objets égaux, mêmes objets ?¶
c’est super important de bien comprendre
quand on crée un nouvel objet
et quand on se contente de retrouver un objet déjà créé
on en reparlera longuement, mais voyons cet exemple pour bien illustrer le concept
%load_ext ipythontutorThe ipythontutor extension is already loaded. To reload it, use:
%reload_ext ipythontutor
%%ipythontutor curInstr=2
a = b = [1, 2]
c = [1, 2]dans ce cas de figure, on a
deux objets de type liste, distincts - car chacune des deux lignes en crée un
et trois variables, dont les deux premières désignent (on dit aussi font référence à, ou réfèrent, ou pointent vers...) le même objet liste
a = b = [1, 2]
c = [1, 2]# les deux premières variables
# réfèrent bien le même objet
a is bTrue# ce n'est pas le cas pour a et c
a is cFalse# par contre les trois variables sont égales
# au sens de == car dans les deux listes on a
# les mêmes valeurs
a == b == cTrueprimer¶
survol du langage à 30.000 pieds
sur quelques exemples hyper simples
pour introduire les notions les plus importantes
notamment fonctions, classes, modules, exceptions, ...
seulement pour introduire le vocabulaire, et donc sans approfondir
primer : les commentaires¶
tout ce qu’il y a après un # est ignoré par l’interpréteur
# programme de test qui ne fait pas grand-chose
L = [1, 2]
x = 5
if x > 3: # on peut commenter où on veut
# mais en pratique c'est mieux de prendre
# toute la ligne comme ceci car on s'efforce
# de garder la largeur de page < 80 caractères
print(L)[1, 2]
primer : indentation et syntaxe¶
contrairement à beaucoup d’autres langages
la mise en page (sauts de ligne et indentations)
fait partie de la syntaxe
ce qui élimine le besoin de
{}oubegin/end
if 2**5 == 32:
print("c'est l'alignement des lignes")
print("qui produit les blocs")
print("pas de sucre syntaxique superflu")
print("genre begin/end ou {}")
else:
print("on ne passe pas ici")c'est l'alignement des lignes
qui produit les blocs
pas de sucre syntaxique superflu
genre begin/end ou {}
primer : types “fournis”¶
avec le langage sont fournis des types de base (batteries included)
nombres:
entiers, flottants, complexes, booléens
containers:
listes, dictionnaires, ensembles, tuples
qui permettent de traiter rapidement pas mal de sujets
primer: librairie standard et écosystème¶
il y a aussi la “librairie standard” qui vient avec plein d’utilitaires:
pathlib: gestion des fichiers, et calculs de cheminsdatetime: date et heurerandom: générateur de nombres aléatoiresitertools: itérations comme permutations, combinaisons, produit cartésien, ...queue: priority queuesla liste est très très longue...
là encore cela signifie qu’on a rapidement accès à des fonctionnalités puissantes, et bien optimisées
et si ce dont on a besoin n’est pas dans la librairie standard,
il y a ... des centaines de milliers de librairies disponibles sur https://pypi.org
y compris notamment numpy, pandas, scikit-learn, et énormément d’autres...
primer : fonction¶
def my_first_function(a, b):
if a <= b:
return a * b
else:
return a + bmy_first_function(10, 2)12my_first_function(2, 10)20brique de base de la réutilisabilité
remarquez la syntaxe orientée bloc
primer : classe¶
class MyFirstClass:
def __init__(self, nom, age):
print("init instance", nom)
self.nom = nom
self.age = age
def __repr__(self):
return f"{self.nom}, {self.age} ans"# si vous préférez on aurait pu appeler la classe 'Person'
# et alors on écrirait:
# person = Person("Jean Dupont", 25)
# mais ici avec le nom que j'ai choisi, on ferait
instance = MyFirstClass("Jean Dupont", 25)init instance Jean Dupont
# et lorsqu'on l'affiche
instanceJean Dupont, 25 ansà quoi ça sert ?
étendre les types de base (fournis par le langage) avec des types spécifiques à votre application
pour pouvoir passer des objets ‘composites’ (encapsulation)
et éventuellement réutiliser par héritage
primer : type hints¶
# grâce aux type hints, on peut donner
# une indication sur le type attendu de la variable
# comme ceci : ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
persons = [] # type: list[MyFirstClass]
# ou encore ici: ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ et ↓↓↓ et ↓↓↓↓↓↓↓↓↓↓↓↓
def search(persons: list[MyFirstClass], nom: str) -> MyFirstClass:
for p in persons:
if p.nom == nom:
return pgroup = [
MyFirstClass("Jean Dupont", 25),
MyFirstClass("Pierre Durand", 42),
]
search(group, "Jean Dupont")init instance Jean Dupont
init instance Pierre Durand
Jean Dupont, 25 ansles type hints, traduites en “annotations de type”
sont entièrement optionnelles (sont ignorées par le langage)
mais aident à lire, à utiliser, et à documenter le code
vérifiables par un outil externe - e.g.
mypy
primer : module¶
# le module standard math s'importe comme ceci
import math
type(math)module# je peux me définir une variable 'pi'
pi = "la tour de Pi"# qui n'interfère pas avec celle définie dans le module
math.pi3.141592653589793le module est une des briques de base de la réutilisabilité:
il permet de mettre un bout de code en commun entre plusieurs applications: une librairie
il correspond (en général) à un fichier (ou répertoire) de source
fonctionne comme un espace de noms
par exemple: ma variable
picoexiste avec celle demath, mais il n’y a pas de conflit
primer : attributs¶
programmation orientée objet
notation
objet.attribut: lorsque vous voyez un.dans le code, c’est qu’on va chercher un attribut dans un objetpeut être utilisé pour ranger de la donnée ou du code
# que ce soit pout accéder à un attribut (de donnée)
p = MyFirstClass("jean", 43)
p.ageinit instance jean
43# ou pour appeler une méthode
x = "abc"
x.upper()'ABC'en fait le . correpond à un mécanisme général, dit de recherche d’attributs, dont on reparlera bien sûr
on a dit plus haut par abus de langage “la variable pi du module math”
en réalité ça correspond en effet à une variable globale au module, mais techniquement lorsqu’on écrit math.pi on fait référence à un attribut du module pi
primer : itérations¶
l’instruction for et les itérateurs permettent de dissocier
la logique d’itération
du traitement à chaque tour de boucle
# partant par exemple d'une liste
liste = [10, 20, 30]# on itére toujours comme ceci
for item in liste:
print(item)10
20
30
# et JAMAIS comme ceci
for i in range(len(liste)):
print(liste[i])10
20
30
on verra qu’avec la fonction enumerate() on peut toujours éviter ce vilainfor i in range(len(truc)) même si dans la boucle on a besoin de i
primer : exceptions¶
en enfin pour terminer, on trouve dans le langage la notion d’exception, qui est maintenant classique
l’idée c’est de pouvoir “remonter la pile des appels” sans avoir à retourner une valeur spéciale qui indiquerait une erreur
# une fonction qui fait boom (parce division par zéro)
# mais pas au premier appel
def boom(n):
if n > 0:
return boom(n-1)
else:
return 1/ntry:
boom(2)
except Exception as exc:
print("BOOM", exc)
print("la vie continue")BOOM division by zero
la vie continue
%load_ext ipythontutorThe ipythontutor extension is already loaded. To reload it, use:
%reload_ext ipythontutor
%%ipythontutor height=500 width=850
# sans exception : le programme crashe
def boom(n):
if n > 0:
return boom(n-1)
else:
return 1/n
boom(2)
print("la vie ne continue pas !")%%ipythontutor height=500 width=850 curInstr=12
# avec exception
def boom(n):
if n > 0:
return boom(n-1)
else:
return 1/n
try:
boom(2)
except Exception as exc:
print("BOOM", exc)
print("la vie continue")