Aller au contenu

Selection

Sélection

On ne veut afficher que les communes qui commencent par Z.

On va donc créer une nouvelle table, en ne sélectionnant dans localisation que les lignes dont le champs nom commence par Z. C'est une opération de sélection : on sélectionne des lignes selon un critère.

communes_selectionnes = []

for l in localisation:
    if l["nom"][0] == "Z":
        communes_selectionnes.append(l)

Compréhension de listes

Au lieu d'écrire la boucle for ci dessus, on aurait aussi pu utiliser une compréhension de list. C'est un aspect de la syntaxe de Python qui permet de décrire une list à partir d'un autre list.

communes_selectionnes = [l for l in localisation if l["nom"][0] == "Z"]

Une compréhension de list à la syntaxe suivante :

[expr for element in liste if condition]

où :

  • liste est la liste d'origine
  • element est la valeur d'un élément de la liste
  • condition est une expression booléenne qui peut utiliser element.
  • expr est une expression qui peut utiliser element.

Pour chaque élément présent dans liste, la valeur de expr est ajoutée à la list produite si condition vaut True.

Par exemple :

l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l2 = [x * 3 for x in l1 if x > 3]
print(l2)

affiche

[12, 15, 18, 21, 24, 27]

Quelques recherches

Exercice 1

Implantez la fonction communes_en_y qui sélectionne les lignes des communes commençant par Y dans la table localisation et les retourne sous forme d'une nouvelle table.

def communes_en_y(localisation):
    communes_selectionnees = []
    for l in localisation:
        if l["nom"][0] == "Y":
            communes_selectionnees.append(l)
    return communes_selectionnees
def communes_en_y(localisation):
    return [l for l in localisation if l["nom"][0] == "Y"]

Exercice 2

Implantez la fonction communes_creuse qui sélectionne les lignes des communes de la Creuse dans la table localisation et les retourne sous forme d'une nouvelle table.

def communes_creuse(localisation): 
        communes_selectionnees = []
        for l in localisation:
            if l["code_postal"][0] == "2" and l["code_postal"][1] == "3":
                communes_selectionnees.append(l)
        return communes_selectionnees
def communes_creuse(localisation):
    return [l for l in localisation if l["code_postal"][0] == "2" and l["code_postal"][1] == "3"]

Exercice 3

Implantez la fonction communes_isere_d qui sélectionne les lignes des communes de l'Isère dont le nom commence par D dans la table localisation et les retourne sous forme d'une nouvelle table.

def communes_isere_d(localisation):
    communes_selectionnees = []
    for l in localisation:
        if l["code_postal"][0] == "3" and l["code_postal"][1] == "8" and l["nom"][0] == "D":
            communes_selectionnees.append(l)
    return communes_selectionnees
def communes_isere_d(localisation):
    return [l for l in localisation if l["code_postal"][0] == "3" and l["code_postal"][1] == "8" and l["nom"][0] == "D"]

Exercice 4

Si ce n'est pas déjà fait, utilisez une fonction pour exprimer la condition de l'exercice 3, afin de rendre le code plus lisible.

def en_isere_en_d(l):
    return l["code_postal"][0] == "3" and l["code_postal"][1] == "8" and l["nom"][0] == "D"

def communes_isere_d(localisation):
    communes_selectionnees = []
    for l in localisation:
        if en_isere_en_d(l):
            communes_selectionnees.append(l)
    return communes_selectionnees
def en_isere_en_d(l):
    return l["code_postal"][0] == "3" and l["code_postal"][1] == "8" and l["nom"][0] == "D"

def communes_isere_d(localisation):
    return [l for l in localisation if en_isere_en_d(l)]

Code générique

Complication

Cette partie peut-être compliquée à comprendre et à expliquer. N'hésitez pas à demander au professeur si vous rencontrez des difficultés.

Si on regarde les codes produits dans les exercices 1 à 4, on peut remarquer que leur structure est similaire : on sélectionne chaque élément de la liste si il vérifie une condition. Le code de parcours et de sélection est le même pour tous les exercices, seule la condition change. On veut maintenant améliorer notre code pour pouvoir faire plusieurs sélections différentes sans avoir à réécrire le code de parcours.

En Python, comme dans beaucoup de langages de programmation, les fonctions sont des valeurs au même titre que les entiers, les chaînes, ... On peut donc mettre des fonctions dans des variables.

def bonjour(nom):
    print(f"Bonjour {nom} !")

f = bonjour #on met la fonction dans une variable
f("Félix") #on appelle la fonction contenue dans la variable

affiche

Bonjour Félix !

Ou encore passer des fonctions en paramètre à d'autres fonctions.

def bonjour():
    print("Bonjour !")

def au_revoir():
    print("Au revoir !)

def repeter2(fonction):
    fonction()
    fonction()

repeter2(bonjour)
repeter2(au_revoir)

Affiche :

Bonjour !
Bonjour !
Au revoir !
Au revoir !

On peut donc créer une fonction selection, qui prends en parametre une table et une fonction représentant une condition de selection, et qui retourne la table résultat de la sélection.

def selection(table, condition):
    resultat = []
    for l in table:
        if condition(l):
            resultat.append(l)
    return resultat
def selection(table, condition):
    return [l for l in table if condition(l)]

Pour faire une nouvelle sélection, on a maintenant seulement besoin d'écrire une nouvelle condition et la passer à la fonction :

def en_isere_en_d(l):
            return l["code_postal"][0] == "3" and l["code_postal"][1] == "8" and l["nom"][0] == "D"

communes_selectionnees = selection(localisation, en_isere_en_d)

Une fonction qui prends un autre fonction en paramètre comme selection, est appelée fonction d'ordre supérieur. Il est important de savoir les utiliser, parce que de nombreuses bibliothèque en fournissent.

TODO (prof) peut etre mieux montrer, schéma etc, la correspondance entre les params de la fonction-valeur et ce qu'elle reçoit

Exercice 5

Utilisez la fonction selection pour implanter la fonction communes_en_z qui sélectionne les lignes des communes dont le nom commence par D dans la table localisation et les retourne sous forme d'une nouvelle table.

Il vous faut définir une fonction de condition, par exemple appelée en_z,

puis la passer à la fonction selection comme paramètre.

def en_z(l):
    return l["nom"][0] == "Z"

def communes_en_z(localisation):
    return selection(localisation, en_z)

Expressions lambda

Finalement, on peut définir des fonctions sans nom par le biais des expressions lambda (ou lambda expression). C'est une manière très concise d'utiliser une fonction d'ordre supérieur.

Pour créer une expression lambda, on utilise la syntaxe suivante :

lambda parametres : expression

parametre est les paramètres de l'expression, comme pour une fonction, et où expression est une expression. Par exemple :

plus_2 = lambda x : x + 2
a = plus_2(5)
#ici, a vaut 7

On peut alors directement exprimer la condition sans passer par une déclaration de fonction classique.

## On sélectionne toutes les communes qui commencent par y
communes_selectionnees = selection(localisation, lambda l : l["nom"][0] == "Y")

Exercice 6

Utilisez la fonction selection pour implanter la fonction communes_en_z qui sélectionne les lignes des communes dont le nom commence par D dans la table localisation et les retourne sous forme d'une nouvelle table. Sans utiliser le mot-clé def.

Cet exercice est dans une sous-section "Expressions lambda". Il vous faut donc sans-doute utiliser une expression lambda ;).

def communes_en_z(localisation):
    return selection(localisation, lambda l : l["nom"][0] == "Z")

TODO (prof) ajouter des tests ici ?