1. Test technique
1.1. Le contexte
Ce cours suppose les bases du langage Python maitrisées. Le test technique ci dessous est là pour s’en assurer.
Ce test couvre la lecture de données, les principales structures de données, l’organisation du code en fonctions et les doctests. Le réussir atteste que vous savez manipuler les éléments essentiels du langage.
Chaque fonction doit être évaluée par les doctests associés. Vous devez obtenir 100 % en 03:00 maximum. Si ce n’est pas le cas, les compétences de base doivent être renforcées.
1.2. Le sujet
1.2.1. Les communes en France
En France, la commune est à la fois une collectivité territoriale et une circonscription administrative.
La réforme des collectivités territoriales de 2010 oblige chaque commune à adhérer à un Etablissement Public de Coopération Intercommunale, qui peut être :
1.2.2. Les données
Les données sont produites par l”INSEE et enrichies et mises en ligne par opendatasoft. Elles sont disponibles dans le fichier population.csv
. Ce fichier est encodé en utf8
.
Les champs sont désignés ci dessous :
Code Officiel Région ;
Nom Officiel Région ;
Code Officiel Département ;
Code Officiel Arrondissement Départemental ;
Code Officiel Commune / Arrondissement Municipal ;
Nom Officiel Commune / Arrondissement Municipal ;
Population municipale ;
Population comptée à part ;
Population totale ;
Année de recensement ;
Année d’entrée en vigueur ;
Année de référence géographique ;
Nom Officiel EPCI ;
Code Officiel EPCI ;
Nom Officiel Département.
L’objectif est d’écrire un ensemble de fonctions permettant de lire et manipuler ces données. On utilisera le fichier squelette population.py
.
1.2.3. Lecture des données
Ecrire une fonction read_file()
:
qui prend en argument un nom de fichier sous forme de chaîne de caractères
Jeter un oeil aux doctests pour des exemples d’appel/retour de la fonction.
Quelques indications :
il sera très pratique d’utiliser la classe
DictReader
du modulecsv
;lors de l’ouverture du fichier, on portera une attention particulière à l’encodage du fichier csv ;
lors de la lecture, on portera une attention particulière au délimiteur utilisé.
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.
1.2.4. Construire la liste des départements
Ecrire une fonction build_list_departements()
:
qui prend en argument la liste de dictionnaires retournée par
read_file()
Jeter un oeil aux doctests pour des exemples d’appel/retour de la fonction.
Quelques indications :
une structure de données est particulièrement appropriée pour construire une liste sans doublons ;
pour certaines lignes, le département n’est pas renseigné ;
la fonction
sorted()
est utile pour trier une séquence.
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.
1.2.5. Construire la liste des communes
De façon similaire, écrire une fonction build_list_communes()
:
qui prend en argument la liste de dictionnaires retournée par
read_file()
Jeter un oeil aux doctests pour des exemples d’appel/retour de la fonction.
Quelques indications :
une structure de données est particulièrement appropriée pour construire une liste sans doublons ;
la fonction
sorted()
est utile pour trier une séquence ;on peut passer une clé de tri multi critères à la fonction
sorted()
.
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.
1.2.6. Rechercher la population d’une commune
Ecrire une fonction get_pop_commune()
:
Jeter un oeil aux doctests pour des exemples d’appel/retour de la fonction.
Quelques indications :
si la commune n’existe pas (ou est mal orthographiée), la fonction ne retourne rien ;
les données dans le fichier ne sont pas forcément ordonnées ;
il sera judicieux de ne pas parcourir plus de données que nécessaire.
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.
1.2.7. Construire un dictionnaire des départements
Ecrire une fonction build_dict_departements()
:
qui prend en argument la liste de dictionnaires retournée par
read_file()
;
Jeter un oeil aux doctests pour des exemples d’appel/retour de la fonction.
Quelques indications :
les données réelles sont rarement (jamais ?) idéalement structurées. Ici l’ambigüité dans la désignation de la commune peut générer des erreurs dans les doctest. La source d’une éventuelle ambigüité :
un même code INSEE/EPCI peut être attribué à deux communes différentes. Par exemple,
Roussac
etSaint-Pardoux-le-Lac
ont le même code INSEE (87128
) ;l’orthographe a pu évoluer entre deux années de recensement :
Coeuvres-et-Valsery
puisCœuvres-et-Valsery
, ouLes Trois Châteaux
puisLes Trois-Châteaux
;il y a pu y avoir des regroupements de communes entre deux années de recensement. Par exemple, la fusion des communes de
Conilhac-de-la-Montagne
et deRoquetaillade
a donné naissance à la commune deRoquetaillade-et-Conilhac
qui a le statut de commune nouvelle ;
selon la façon dont sont gérées les données ambigües, l’exécution des fonctions peut conduire à un résultat différent de ceux utilisés pour les doctests ;
un dictionnaire multi dimensionnel est une structure de données appropriée pour ce problème ;
avec le
dict
standard, il faut gérer la présence/absence de clés. En supposant quedata
est ici une liste de tuplesd = dict() for dpt, commune, annee, pop in data: if dpt not in d.keys(): d[dpt] = dict() if commune not in d[dpt].keys(): d[dpt][commune] = dict() if annee not in d[dpt][commune].keys(): d[dpt][commune][annee] = dict() d[dpt][commune][annee] = pop
l’utilisation d’un
defaultdict
à plusieurs dimensions facilite le travail:from collections import defaultdict def multi_dict(K, type): if K == 1: return defaultdict(type) else: return defaultdict(lambda: multi_dict(K-1, type)) md = multi_dict(3, str) for dpt, commune, annee, pop in data: md[dpt][commune][annee] = pop # si la clé n'existe pas, un :class:`~collections.defaultdict` est créé
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.
1.2.8. Extraire les données par département
Ecrire une fonction stat_by_dpt()
:
qui prend en argument le dictionnaire des départements (retourné par build_dict_departements()) et le département d’intérêt (str) ;
et retourne un tuple dont le premier élément est le nombre de communes du département (
int
) et le second élément la population totale du département (int
).
Utiliser la fonction main()
pour la mise au point, puis valider la fonction en exécutant les doctests associés.