GUIDE COMPLET
Certification Python 3 — Journee 2
Structures imbriquees, Map/Filter, API REST, POO, Heritage
Ce document couvre le Module 2 complet : structures imbriquees, JSON, Map/Filter/Comprehension,
API REST avec requests, Programmation Orientee Objet, Heritage, Polymorphisme.
1. STRUCTURES IMBRIQUEES (NESTED DATA)
1.1 Listes imbriquees
Une liste peut contenir n'importe quel type, y compris d'autres listes.
# Liste de listes
nested = [['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h']]
# Acces : deux indices successifs
nested[1] # ['d', 'e']
nested[1][0] # 'd'
nested[0][2] # 'c'
# Liste contenant des types mixtes
liste = ['mot', 100, 15.23, True, [10, 20]]
liste[4] # [10, 20]
liste[4][1] # 20
1.2 Dictionnaires imbriques
# Dictionnaire imbrique profond
info = {
'personal_data': {
'name': 'Lauren',
'age': 20,
'physical_features': {
'color': {'eye': 'blue', 'hair': 'brown'},
'height': "5'8"
}
},
'other': {
'favorite_colors': ['purple', 'green', 'blue']
}
}
Guide Python 3 — Journee 2 | Page 1
# Acces aux donnees profondes
info['personal_data']['name'] # 'Lauren'
info['personal_data']['physical_features']['color']['eye'] # 'blue'
info['other']['favorite_colors'][0] # 'purple'
ASTUCE : Pour acceder a une valeur profonde, chainer les crochets un par un.
PIEGE : Si une cle intermediaire n'existe pas => KeyError !
Utiliser .get() a chaque niveau pour eviter les erreurs.
1.3 Iterations imbriquees
# Parcourir une liste de listes
nested = [['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h']]
for sous_liste in nested:
for element in sous_liste:
print(element)
# Avec condition sur le type (liste heterogene)
nested_mix = [1, 2, ['a', 'b'], ['c', 'd']]
for x in nested_mix:
if type(x) is list:
for y in x:
print(' niveau 2:', y)
else:
print('niveau 1:', x)
# Collecter des elements d'une structure imbriquee
L = [['apples', 'bananas'], ['carrots', 'beans'], ['root beer']]
b_strings = [] # accumulateur
for sous_liste in L:
for element in sous_liste:
if 'b' in element:
b_strings.append(element)
1.4 Deep Copy vs Shallow Copy — TRES IMPORTANT
# SHALLOW COPY : copie de surface
original = [['dogs', 'puppies'], ['cats', 'kittens']]
shallow = original[:] # ou [Link]()
shallow is original # False (objets differents)
shallow[0] is original[0] # TRUE ! (les sous-listes sont partagees !)
shallow[0].append('wolf') # MODIFIE AUSSI original[0] !
# DEEP COPY : copie complete independante
Guide Python 3 — Journee 2 | Page 2
import copy
deep = [Link](original)
deep[0].append('wolf') # NE modifie PAS original
REGLE : liste[:] ou .copy() = shallow copy => les sous-listes restent partagees !
Pour copier completement une structure imbriquee => import copy; [Link](obj)
Ce piege concerne aussi les dicts imbriques et tout objet mutable imbrique.
2. JSON — JavaScript Object Notation
2.1 Principe
Format texte d'echange de donnees. Ressemble aux dicts/listes Python. Tres utilise avec les API.
Type Python Equivalent JSON Remarque
dict {} object {} Cles doivent etre des strings en
JSON
list [] array [] Identique
str string Guillemets doubles obligatoires
en JSON
int / float number Identique
True / False true / false Minuscules en JSON !
None null Minuscule en JSON !
2.2 [Link]() et [Link]()
import json
# JSON string => objet Python (loads = load string)
json_str = '{"resultCount": 25, "results": [{"id": 10}]}'
data = [Link](json_str) # => dict Python
print(type(data)) # <class 'dict'>
print(data['resultCount']) # 25
# Objet Python => JSON string (dumps = dump string)
d = {'key1': {'a': 90, 'b': True}, 'key2': [1, 2, 3]}
json_str = [Link](d) # compact
# Affichage formate (indente)
print([Link](d, sort_keys=True, indent=2))
ASTUCE : [Link]() = lire une chaine JSON => Python
ASTUCE : [Link]() = ecrire un objet Python => chaine JSON
Moyen mnemotechnique : loads = 'load from string', dumps = 'dump to string'
Guide Python 3 — Journee 2 | Page 3
2.3 Extraire des donnees imbriquees
# Exemple : reponse d'une API (structure imbriquee type Twitter/iTunes)
data = {
'resultCount': 3,
'results': [
{'trackName': 'Song A', 'artistName': 'Artist 1'},
{'trackName': 'Song B', 'artistName': 'Artist 2'},
]
}
# Parcourir les resultats
for item in data['results']:
print(item['trackName'], '-', item['artistName'])
# Acces direct
data['results'][0]['trackName'] # 'Song A'
len(data['results']) # 2
3. MAP, FILTER ET LIST COMPREHENSION
3.1 map()
Applique une fonction a chaque element d'une sequence. Retourne un objet map (pas une liste
directement).
# Syntaxe : map(fonction, sequence)
# Retourne un objet map => convertir avec list()
# Exemple basique
nombres = [2, 5, 9]
doubles = list(map(lambda x: x * 2, nombres)) # [4, 10, 18]
# Avec une vraie fonction
def ajouter_prefix(mot):
return 'Fruit: ' + mot
fruits = ['pomme', 'kiwi', 'mangue']
result = list(map(ajouter_prefix, fruits))
# => ['Fruit: pomme', 'Fruit: kiwi', 'Fruit: mangue']
# Equivalent en list comprehension
result = ['Fruit: ' + mot for mot in fruits]
3.2 filter()
Garde uniquement les elements pour lesquels la fonction retourne True.
# Syntaxe : filter(fonction, sequence)
Guide Python 3 — Journee 2 | Page 4
# Retourne un objet filter => convertir avec list()
# Garder les nombres pairs
nombres = [1, 2, 3, 4, 5, 6]
pairs = list(filter(lambda x: x % 2 == 0, nombres))
# => [2, 4, 6]
# Garder les pays commencant par 'B'
pays = ['Canada', 'Botswana', 'Spain', 'Britain', 'Belgium']
b_pays = list(filter(lambda x: x[0] == 'B', pays))
# => ['Botswana', 'Britain', 'Belgium']
# Garder les mots contenant 'w'
mots = ['plums', 'watermelon', 'kiwi', 'strawberries']
avec_w = list(filter(lambda x: 'w' in x, mots))
# => ['watermelon', 'kiwi', 'strawberries']
3.3 List Comprehension — LA SYNTAXE COMPLETE
# Syntaxe complete
[expression for variable in sequence if condition]
# Sans condition (map)
[x * 2 for x in [1, 2, 3, 4]] # [2, 4, 6, 8]
# Avec condition (filter)
[x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]
# Avec condition ET transformation (map + filter)
[x**2 for x in range(10) if x % 2 == 0] # [0, 4, 16, 36, 64]
# Expression ternaire dans la comprehension
[x**3 if x%2==0 else x**2 for x in range(5)] # [0, 1, 8, 9, 64]
# Sur tuples : extraire le prenom
people = [('Snow','Jon'), ('Stark','Arya'), ('Lannister','Cersei')]
prenoms = [p[1] for p in people] # ['Jon', 'Arya', 'Cersei']
# Filtrer par condition sur le tuple
# Etudiants avec note >= 70
students = [('Tommy',95), ('Linda',63), ('Carl',70), ('Bob',100)]
admis = [nom for (nom, note) in students if note >= 70]
# => ['Tommy', 'Carl', 'Bob']
3.4 zip() — Combiner deux listes
# zip() combine deux listes element par element => liste de tuples
Guide Python 3 — Journee 2 | Page 5
L1 = [3, 4, 5]
L2 = [1, 2, 3]
# Addition element par element
sommes = [x1 + x2 for (x1, x2) in list(zip(L1, L2))]
# => [4, 6, 8]
# Filtrer avec zip
l1 = ['left', 'up', 'front']
l2 = ['right', 'down', 'back']
# Garder les paires dont LES DEUX elements ont len >= 3
opposites = [(x1, x2) for (x1, x2) in zip(l1, l2) if len(x1) >= 3 and len(x2) >= 3]
# Trouver especes en danger (population < 2500)
species = ['panda', 'rhino', 'bear']
populations = [1500, 400, 35000]
endangered = [s for (s, pop) in zip(species, populations) if pop < 2500]
COMPARAISON map/filter vs list comprehension :
map(f, liste) <==> [f(x) for x in liste]
filter(f, liste) <==> [x for x in liste if f(x)]
map + filter chaines <==> [f(x) for x in liste if condition]
La list comprehension est plus lisible et pythonique => preferee en pratique.
4. API REST — RECUPERER DES DONNEES DU WEB
4.1 Principes
• API = Interface de communication entre applications
• REST = Representational State Transfer, base sur HTTP
• Les requetes se font via des URLs avec parametres
• Les reponses sont generalement en format JSON
4.2 Anatomie d'une URL REST
[Link]
# |_base URL_________|?|__parametres key=value_________|
# separateur = ?
# parametres separes par &
# Decomposition :
# base URL : [Link]
# param 1 : term = Ann+Arbor
# param 2 : entity = podcast
Guide Python 3 — Journee 2 | Page 6
4.3 [Link]() — Le module essentiel
import requests
import json
# Methode 1 : URL directe avec parametres dans l'URL
response = [Link]('[Link]
# Methode 2 : parametres separes (RECOMMANDE)
params = {'term': 'Ann Arbor', 'entity': 'podcast'}
response = [Link]('[Link] params=params)
# Proprietes de la reponse
[Link] # URL complete avec parametres
response.status_code # 200 = OK, 404 = Not Found, 500 = Erreur serveur
[Link] # contenu brut (chaine)
[Link]() # parse automatiquement le JSON => dict/list Python
# Traiter la reponse JSON
data = [Link]()
for item in data['results']:
print(item['trackName'])
4.4 Exemple complet iTunes API
import requests
import json
# Parametres de recherche
parameters = {'term': 'Ann Arbor', 'entity': 'podcast'}
# Appel a l'API
response = [Link]('[Link] params=parameters)
# Verification du statut
print(response.status_code) # 200 si OK
# Conversion en objet Python
data = [Link]([Link]) # ou [Link]()
# Affichage structure
print(data['resultCount'])
for r in data['results']:
print(r['trackName'])
4.5 Fonction get_rhymes — Exemple de bonne pratique
def get_rhymes(word):
Guide Python 3 — Journee 2 | Page 7
base_url = '[Link]
params = {}
params['rel_rhy'] = word # mot dont on cherche les rimes
params['max'] = '4' # nombre max de resultats
response = [Link](base_url, params=params)
return [Link]() # retourne un objet Python
# Utilisation
resultats = get_rhymes('day')
for mot in resultats:
print(mot['word'])
BONNE PRATIQUE : Toujours verifier response.status_code avant de traiter.
BONNE PRATIQUE : Passer les params en dict a [Link]() => gestion automatique encodage.
ASTUCE : [Link]() = [Link]([Link]), les deux fonctionnent.
CACHE : Pour eviter les appels repetitifs, utiliser requests_with_caching.
5. PROGRAMMATION ORIENTEE OBJET (POO)
5.1 Concepts fondamentaux
Concept Definition Exemple
Classe Modele / plan de construction class Point:
Objet / Instance Exemplaire cree depuis la p = Point(3, 4)
classe
Attribut Variable propre a l'objet self.x = 3
Methode Fonction propre a la classe def getX(self):
Constructeur Methode __init__, cree l'objet def __init__(self, x, y):
self Reference a l'objet courant self.x = initX
5.2 Creer une classe — Syntaxe complete
class Point:
""" Classe representant un point 2D. """
# Constructeur : appele automatiquement a la creation
def __init__(self, initX, initY):
self.x = initX # attribut d'instance
self.y = initY
# Methodes
def getX(self):
return self.x
Guide Python 3 — Journee 2 | Page 8
def getY(self):
return self.y
def distanceFromOrigin(self):
return ((self.x ** 2) + (self.y ** 2)) ** 0.5
# Methode speciale : representation en chaine
def __str__(self):
return 'x = {}, y = {}'.format(self.x, self.y)
# Methode utilisant un autre objet
def halfway(self, other):
mx = (self.x + other.x) / 2
my = (self.y + other.y) / 2
return Point(mx, my) # retourne un NOUVEL objet
# Utilisation
p1 = Point(3, 4)
p2 = Point(0, 0)
print(p1) # x = 3, y = 4 (via __str__)
print([Link]()) # 3
print([Link]()) # 5.0
milieu = [Link](p2) # Point(1.5, 2.0)
REGLE : Toute methode d'instance prend 'self' comme 1er parametre.
REGLE : Pour acceder aux attributs depuis une methode => [Link]
PIEGE : Oublier 'self' => la methode ne connait pas ses propres attributs !
ASTUCE : __str__ permet d'afficher l'objet proprement avec print()
5.3 Exemple Complet : Classe Compte Bancaire
class Compte:
def __init__(self, nc, proprio, solde):
[Link] = nc
[Link] = proprio
[Link] = solde
def crediter(self, valeur):
[Link] += valeur
def debiter(self, valeur):
[Link] -= valeur
def afficher_detail(self):
print('Compte:', [Link])
print('Proprietaire:', [Link])
Guide Python 3 — Journee 2 | Page 9
print('Solde:', [Link])
def __str__(self):
return f'Compte {[Link]} - {[Link]} : {[Link]}'
# Creation et utilisation
c = Compte(101, 'Ali', 1000)
[Link](500) # solde = 1500
[Link](200) # solde = 1300
c.afficher_detail()
print(c) # via __str__
6. HERITAGE, POLYMORPHISME ET ABSTRACTION
6.1 Principe de l'Heritage
Une classe fille herite de TOUS les attributs et methodes de la classe mere.
• Reutilisation de code
• Redefinition (override) de methodes
• Organisation pour grands projets
6.2 Syntaxe de base
# Classe mere (parent)
class Animal:
def __init__(self, nom, age):
[Link] = nom
[Link] = age
def parler(self):
print('...')
def __str__(self):
return f'{[Link]}, {[Link]} ans'
# Classe fille (enfant) : herite de Animal
class Chien(Animal): # <- Animal entre parentheses
def __init__(self, nom, age, race):
Animal.__init__(self, nom, age) # appel constructeur mere
[Link] = race # nouvel attribut
def parler(self): # SURCHARGE de la methode
print('Wouf !')
def chercher(self): # NOUVELLE methode
print([Link], 'cherche la balle')
# Utilisation
Guide Python 3 — Journee 2 | Page 10
d = Chien('Rex', 3, 'Labrador')
print(d) # 'Rex, 3 ans' (heritee de Animal)
[Link]() # 'Wouf !' (methode surchargee)
[Link]() # 'Rex cherche la balle' (nouvelle methode)
6.3 Exemple : Compte Bancaire avec Heritage
class Compte: # CLASSE MERE
def __init__(self, nc, proprio, s):
[Link] = nc
[Link] = proprio
[Link] = s
def crediter(self, v): [Link] += v
def debiter(self, v): [Link] -= v
def afficher_detail(self):
print('Compte:', [Link], '| Solde:', [Link])
class CompteCourant(Compte): # CLASSE FILLE 1
def __init__(self, nc, proprio, s):
Compte.__init__(self, nc, proprio, s)
# Herite de tout, rien de nouveau
class CompteEpargne(Compte): # CLASSE FILLE 2
def __init__(self, nc, proprio, s, taux):
Compte.__init__(self, nc, proprio, s) # appel constructeur mere
self.taux_interet = taux # attribut supplementaire
def afficher_detail(self): # SURCHARGE
super().afficher_detail()
print('Taux:', self.taux_interet)
# Usage
c1 = CompteCourant(100, 'Ali', 1000)
c2 = CompteEpargne(200, 'Sara', 5000, 0.05)
c1.afficher_detail()
c2.afficher_detail()
6.4 Indicateurs de visibilite
Ecriture Visibilite
[Link] PUBLIC : accessible partout (hors et dans la classe)
self.__attribut PRIVE : accessible SEULEMENT dans la classe (double
underscore)
self._attribut PROTEGE : accessible dans la classe ET les classes filles
(simple underscore)
Guide Python 3 — Journee 2 | Page 11
class MaClasse:
def __init__(self):
[Link] = 'tout le monde voit'
self.__prive = 'seulement cette classe'
self._protege = 'classe + classes filles'
6.5 Abstraction — Methodes abstraites
Methode declaree dans la classe mere mais non implementee => les classes filles DOIVENT
l'implementer.
from abc import ABC, abstractmethod
class Forme(ABC): # classe abstraite
@abstractmethod
def calculer_aire(self): # methode abstraite (pas d'implementation)
pass
class Cercle(Forme):
def __init__(self, rayon):
[Link] = rayon
def calculer_aire(self): # OBLIGATOIRE d'implementer
return 3.14 * [Link] ** 2
class Rectangle(Forme):
def __init__(self, l, h):
self.l = l; self.h = h
def calculer_aire(self):
return self.l * self.h
6.6 super() — Appeler la classe mere
# Deux facons d'appeler la methode de la classe mere :
# Methode 1 : explicite (vue dans le cours)
class Fille(Mere):
def __init__(self, a, b, c):
Mere.__init__(self, a, b) # appel explicite avec self
self.c = c
# Methode 2 : super() (recommandee en Python 3)
class Fille(Mere):
def __init__(self, a, b, c):
super().__init__(a, b) # appel via super(), sans self
self.c = c
Guide Python 3 — Journee 2 | Page 12
7. TABLEAU RECAPITULATIF POO
Concept Syntaxe Usage
Definir classe class MaClasse: Cree un nouveau type
Constructeur def __init__(self, ...): Initialise l'objet
Attribut [Link] = valeur Donnee de l'objet
Methode def methode(self, ...): Comportement de l'objet
__str__ def __str__(self): Representation print()
Heritage class Fille(Mere): Heriter d'une classe
Appel mere Mere.__init__(self,...) Constructeur parent
Super super().__init__(...) Equiv. recommandee
Public [Link] Accessible partout
Prive self.__attr Classe seulement
Protege self._attr Classe + filles
Abstrait @abstractmethod Oblige implementation
8. PIEGES FREQUENTS — JOURNEE 2
PIEGE 1 : Shallow copy vs Deep copy
nested[:] copie la liste exterieure mais PAS les sous-listes => modifier sous-liste modifie l'original !
Solution : import copy; [Link](obj)
PIEGE 2 : map() et filter() ne retournent PAS des listes
map(f, l) retourne un objet <map> => toujours faire list(map(f, l))
Idem pour filter() => list(filter(f, l))
PIEGE 3 : JSON - true/false/null en minuscules
En JSON : true, false, null (pas True, False, None comme en Python !)
[Link]() s'en occupe automatiquement lors de la conversion
PIEGE 4 : Oublier 'self' dans les methodes
Toute methode d'instance doit avoir 'self' en premier parametre.
Sans self => la methode ne sait pas de quel objet elle parle => erreur !
PIEGE 5 : Modifier attribut via methode sans self
Dans une methode : nom = 'Ali' cree une variable LOCALE, pas [Link] !
Toujours ecrire : [Link] = 'Ali' pour modifier l'attribut de l'objet.
Guide Python 3 — Journee 2 | Page 13
PIEGE 6 : Heritage sans appel au constructeur mere
Si la classe fille a __init__ elle DOIT appeler Mere.__init__(self,...) ou super().__init__(...)
Sinon les attributs de la classe mere ne sont pas initialises => AttributeError !
PIEGE 7 : KeyError sur dict imbrique
data['results'][0]['clé_inexistante'] => KeyError
Utiliser .get() : data['results'][0].get('cle', valeur_defaut)
Bonne chance a l'examen !
Guide Python 3 — Journee 2 | Page 14