0%
Structures de données en Python : listes, tuples, dictionnaires et ensembles

Structures de données

Organisez et manipulez vos données efficacement

10-15 min

Structures de données en Python : listes, tuples, dictionnaires et ensembles

Les structures de données sont des formats spécialisés pour organiser, stocker et manipuler des informations. Python dispose de plusieurs structures de données intégrées qui facilitent la gestion des collections d’éléments. Dans ce tutoriel, nous allons explorer les quatre structures de données principales de Python : listes, tuples, dictionnaires et ensembles.

Comprendre ces structures et savoir quand utiliser chacune d’elles est essentiel pour écrire du code Python efficace et élégant.

Listes

Les listes sont l’une des structures de données les plus polyvalentes et fréquemment utilisées en Python. Une liste est une collection ordonnée et modifiable d’éléments.

Création de listes

# Liste vide
ma_liste = []

# Liste avec des éléments
nombres = [1, 2, 3, 4, 5]
fruits = ["pomme", "banane", "orange"]
mixte = [1, "hello", 3.14, True]  # Peut contenir différents types

# Création avec la fonction list()
caracteres = list("Python")  # ['P', 'y', 't', 'h', 'o', 'n']

Accès aux éléments d’une liste

Les éléments d’une liste sont indexés à partir de 0.

fruits = ["pomme", "banane", "orange", "fraise", "kiwi"]

# Accès par index positif (depuis le début)
premier_fruit = fruits[0]  # "pomme"
troisieme_fruit = fruits[2]  # "orange"

# Accès par index négatif (depuis la fin)
dernier_fruit = fruits[-1]  # "kiwi"
avant_dernier = fruits[-2]  # "fraise"

# Découpage (slicing)
deux_premiers = fruits[0:2]  # ["pomme", "banane"]
du_deuxieme_au_quatrieme = fruits[1:4]  # ["banane", "orange", "fraise"]
tous_sauf_premier = fruits[1:]  # ["banane", "orange", "fraise", "kiwi"]
trois_premiers = fruits[:3]  # ["pomme", "banane", "orange"]

Modification des listes

fruits = ["pomme", "banane", "orange"]

# Modification d'un élément
fruits[1] = "poire"  # ["pomme", "poire", "orange"]

# Ajout d'éléments
fruits.append("fraise")  # Ajoute à la fin: ["pomme", "poire", "orange", "fraise"]
fruits.insert(1, "kiwi")  # Insère à l'index 1: ["pomme", "kiwi", "poire", "orange", "fraise"]
fruits.extend(["cerise", "raisin"])  # Ajoute plusieurs éléments: ["pomme", "kiwi", "poire", "orange", "fraise", "cerise", "raisin"]

# Suppression d'éléments
fruits.remove("poire")  # Supprime la première occurrence de "poire"
fruit_supprime = fruits.pop(2)  # Supprime et retourne l'élément à l'index 2
del fruits[0]  # Supprime l'élément à l'index 0
fruits.clear()  # Vide la liste complètement

Opérations courantes sur les listes

nombres = [3, 1, 4, 1, 5, 9, 2, 6]

# Longueur
longueur = len(nombres)  # 8

# Minimum et maximum
minimum = min(nombres)  # 1
maximum = max(nombres)  # 9

# Somme
total = sum(nombres)  # 31

# Tri
nombres.sort()  # Trie la liste en place: [1, 1, 2, 3, 4, 5, 6, 9]
nombres_decroissants = sorted(nombres, reverse=True)  # Retourne une nouvelle liste triée: [9, 6, 5, 4, 3, 2, 1, 1]

# Inversion
nombres.reverse()  # Inverse la liste en place

# Comptage
occurrences_de_1 = nombres.count(1)  # 2

# Recherche d'index
premier_index_de_1 = nombres.index(1)  # Index de la première occurrence de 1

Compréhension de liste

La compréhension de liste est une syntaxe concise pour créer des listes basées sur des séquences existantes.

# Sans compréhension de liste
carres = []
for x in range(10):
    carres.append(x**2)

# Avec compréhension de liste
carres = [x**2 for x in range(10)]  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Avec condition
nombres_pairs = [x for x in range(20) if x % 2 == 0]  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Compréhension de liste plus complexe
matrice = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
aplati = [nombre for ligne in matrice for nombre in ligne]  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Cas d’usage courants des listes

Les listes sont idéales quand vous avez besoin de :

  • Stocker une collection d’éléments dans un ordre spécifique
  • Modifier fréquemment la collection (ajouter/supprimer des éléments)
  • Accéder aux éléments par leur position
  • Stocker des doublons

Exemples d’applications :

  • Liste de tâches
  • Historique d’actions
  • Files d’attente de traitement
  • Séries temporelles de données

Tuples

Les tuples sont similaires aux listes, mais ils sont immuables (ne peuvent pas être modifiés après leur création). Cette caractéristique les rend plus efficaces en termes de mémoire et de performances.

Création de tuples

# Tuple vide
mon_tuple = ()

# Tuple avec un seul élément (nécessite une virgule)
singleton = (42,)

# Tuple avec plusieurs éléments
coordonnees = (10, 20)
personne = ("Alice", 30, "Ingénieure")

# Création sans parenthèses (packing)
autre_tuple = 1, 2, 3

# Création avec la fonction tuple()
caracteres = tuple("Python")  # ('P', 'y', 't', 'h', 'o', 'n')

Accès aux éléments d’un tuple

L’accès aux éléments d’un tuple fonctionne comme pour les listes :

coordonnees = (10, 20, 30, 40, 50)

x = coordonnees[0]  # 10
y = coordonnees[1]  # 20
dernier = coordonnees[-1]  # 50
sous_tuple = coordonnees[1:4]  # (20, 30, 40)

Déballage de tuple (unpacking)

Une caractéristique particulièrement utile des tuples est le déballage :

# Déballage basique
point = (10, 20)
x, y = point  # x = 10, y = 20

# Déballage avec * pour capturer plusieurs éléments
premier, *milieu, dernier = (1, 2, 3, 4, 5)
# premier = 1, milieu = [2, 3, 4], dernier = 5

# Échange de variables
a, b = 1, 2
a, b = b, a  # a = 2, b = 1

Opérations sur les tuples

coordonnees = (10, 20, 30)
plus_dimensions = coordonnees + (40, 50)  # Concaténation: (10, 20, 30, 40, 50)
repete = coordonnees * 2  # Répétition: (10, 20, 30, 10, 20, 30)

Méthodes de tuple

Comme les tuples sont immuables, ils ont moins de méthodes que les listes :

nombres = (3, 1, 4, 1, 5, 9, 2)

longueur = len(nombres)  # 7
occurrences_de_1 = nombres.count(1)  # 2
premier_index_de_1 = nombres.index(1)  # 1

Cas d’usage courants des tuples

Les tuples sont préférables lorsque :

  • Vous avez une collection d’éléments qui ne changera pas
  • Vous voulez empêcher la modification accidentelle des données
  • Vous avez besoin d’une clé hashable pour les dictionnaires (les listes ne peuvent pas être des clés)
  • Vous retournez plusieurs valeurs d’une fonction

Exemples d’applications :

  • Coordonnées (x, y, z)
  • Enregistrements de base de données
  • Clés composées
  • Valeurs RGB des couleurs
  • Paramètres de configuration fixés

Dictionnaires

Les dictionnaires sont des collections non ordonnées de paires clé-valeur. Ils permettent un accès, une insertion et une suppression rapides des éléments par clé.

Création de dictionnaires

# Dictionnaire vide
mon_dict = {}

# Dictionnaire avec des paires clé-valeur
etudiant = {
    "nom": "Martin",
    "age": 22,
    "cours": ["Mathématiques", "Informatique", "Physique"]
}

# Création avec la fonction dict()
coordonnees = dict(x=10, y=20, z=30)

# Création à partir de tuples clé-valeur
items = [("pomme", 3), ("banane", 5), ("orange", 2)]
inventaire = dict(items)

# Dictionnaire par compréhension
carre_des_nombres = {x: x**2 for x in range(6)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

Accès et modification des valeurs

etudiant = {
    "nom": "Martin",
    "age": 22,
    "cours": ["Mathématiques", "Informatique", "Physique"]
}

# Accès aux valeurs
nom = etudiant["nom"]  # "Martin"

# Modification des valeurs
etudiant["age"] = 23
etudiant["cours"].append("Chimie")

# Accès sécurisé avec get()
telephone = etudiant.get("telephone")  # None car la clé n'existe pas
telephone = etudiant.get("telephone", "Non spécifié")  # Valeur par défaut "Non spécifié"

# Ajout d'une nouvelle paire clé-valeur
etudiant["email"] = "martin@example.com"

# Suppression
cours = etudiant.pop("cours")  # Supprime et retourne la valeur
del etudiant["age"]  # Supprime la paire clé-valeur
etudiant.clear()  # Vide le dictionnaire

Méthodes de dictionnaire

produits = {
    "pomme": 0.80,
    "banane": 0.50,
    "orange": 0.70
}

# Récupération des clés, valeurs et items
cles = produits.keys()  # dict_keys(['pomme', 'banane', 'orange'])
valeurs = produits.values()  # dict_values([0.8, 0.5, 0.7])
items = produits.items()  # dict_items([('pomme', 0.8), ('banane', 0.5), ('orange', 0.7)])

# Mise à jour du dictionnaire
nouveaux_produits = {"kiwi": 1.20, "banane": 0.55}
produits.update(nouveaux_produits)  # Ajoute "kiwi" et modifie le prix de "banane"

# Vérification de l'existence d'une clé
if "pomme" in produits:
    print("Le prix des pommes est", produits["pomme"])

Itération sur les dictionnaires

produits = {
    "pomme": 0.80,
    "banane": 0.50,
    "orange": 0.70
}

# Itération sur les clés (comportement par défaut)
for produit in produits:
    print(produit)

# Itération sur les valeurs
for prix in produits.values():
    print(prix)

# Itération sur les paires clé-valeur
for produit, prix in produits.items():
    print(f"{produit}: {prix}€")

Dictionnaires imbriqués

# Dictionnaire de dictionnaires
etudiants = {
    "101": {
        "nom": "Alice",
        "age": 22,
        "cours": ["Math", "Informatique"]
    },
    "102": {
        "nom": "Bob",
        "age": 21,
        "cours": ["Physique", "Biologie"]
    }
}

# Accès aux éléments imbriqués
nom_etudiant_102 = etudiants["102"]["nom"]  # "Bob"
cours_alice = etudiants["101"]["cours"][1]  # "Informatique"

Cas d’usage courants des dictionnaires

Les dictionnaires sont parfaits pour :

  • Les collections où vous recherchez des éléments par une clé unique
  • Le stockage de données associatives (paires clé-valeur)
  • Les tables de hachage rapides pour la recherche
  • La représentation d’objets avec des attributs

Exemples d’applications :

  • Cache de données
  • Comptage de fréquences
  • Bases de données en mémoire
  • Paramètres de configuration
  • Stockage de propriétés d’objets JSON

Ensembles

Les ensembles (sets) sont des collections non ordonnées d’éléments uniques. Ils sont optimisés pour tester l’appartenance et éliminer les doublons.

Création d’ensembles

# Ensemble vide (ne peut pas utiliser {}, car cela crée un dictionnaire vide)
mon_ensemble = set()

# Ensemble avec des éléments
couleurs = {"rouge", "vert", "bleu"}

# Création à partir d'une liste (élimine les doublons)
nombres = set([1, 2, 2, 3, 4, 4, 5])  # {1, 2, 3, 4, 5}

# Ensemble par compréhension
nombres_pairs = {x for x in range(10) if x % 2 == 0}  # {0, 2, 4, 6, 8}

Opérations sur les ensembles

fruits1 = {"pomme", "banane", "orange"}
fruits2 = {"orange", "kiwi", "ananas"}

# Ajout et suppression d'éléments
fruits1.add("fraise")
fruits1.remove("banane")  # Lève une erreur si l'élément n'existe pas
fruits1.discard("cerise")  # Ne lève pas d'erreur si l'élément n'existe pas
element = fruits1.pop()  # Supprime et retourne un élément arbitraire
fruits1.clear()  # Vide l'ensemble

# Vérification d'appartenance
"orange" in fruits2  # True
"banane" in fruits2  # False

Opérations ensemblistes

Les ensembles permettent d’effectuer des opérations mathématiques ensemblistes :

A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# Union (éléments qui sont dans A OU dans B)
union = A | B  # {1, 2, 3, 4, 5, 6, 7, 8}
# ou
union = A.union(B)

# Intersection (éléments qui sont dans A ET dans B)
intersection = A & B  # {4, 5}
# ou
intersection = A.intersection(B)

# Différence (éléments qui sont dans A mais PAS dans B)
difference = A - B  # {1, 2, 3}
# ou
difference = A.difference(B)

# Différence symétrique (éléments qui sont dans A OU B mais PAS dans les deux)
diff_sym = A ^ B  # {1, 2, 3, 6, 7, 8}
# ou
diff_sym = A.symmetric_difference(B)

# Vérifier si un ensemble est un sous-ensemble d'un autre
est_sous_ensemble = {1, 2}.issubset(A)  # True

# Vérifier si un ensemble est un sur-ensemble d'un autre
est_sur_ensemble = A.issuperset({1, 2})  # True

Ensembles gelés (frozenset)

Un frozenset est un ensemble immuable, ce qui le rend hashable. Il peut être utilisé comme clé de dictionnaire.

# Création d'un frozenset
couleurs_primaires = frozenset(["rouge", "bleu", "jaune"])

# Utilisation comme clé de dictionnaire
groupes_couleurs = {
    frozenset(["rouge", "bleu", "jaune"]): "primaires",
    frozenset(["violet", "orange", "vert"]): "secondaires"
}

Cas d’usage courants des ensembles

Les ensembles sont particulièrement utiles pour :

  • Éliminer les doublons d’une collection
  • Tester rapidement l’appartenance d’éléments
  • Effectuer des opérations mathématiques sur des ensembles
  • Trouver les éléments uniques ou communs entre collections

Exemples d’applications :

  • Filtrage de doublons
  • Analyse de données uniques
  • Opérations sur des ensembles de tags
  • Gestion de permissions d’utilisateurs
  • Représentation de graphes (théorie des ensembles)

Choisir la bonne structure de données

Chaque structure de données a ses forces et ses faiblesses. Voici un tableau comparatif pour vous aider à choisir la plus adaptée à votre besoin :

StructureOrdonnéeModifiableÉléments indexésÉlément clé-valeurÉléments uniquesCas d’usage typique
ListeCollection ordonnée modifiable
TupleCollection ordonnée immuable
Dictionnaire❌¹✅ (clés)Mappage clé-valeur
EnsembleÉlimination des doublons, opérations ensemblistes

¹ Depuis Python 3.7, les dictionnaires conservent l’ordre d’insertion, mais ils ne sont pas considérés comme intrinsèquement ordonnés dans leur conception.

Conseils pour choisir la structure appropriée

  • Utilisez une liste quand l’ordre et la modification sont importants
  • Utilisez un tuple pour des données en lecture seule ou des clés composites
  • Utilisez un dictionnaire pour des recherches rapides par clé
  • Utilisez un ensemble quand l’unicité et les opérations ensemblistes sont nécessaires

Exemple pratique : Analyse de données

Voici un exemple qui utilise toutes les structures de données pour analyser des ventes :

# Données de ventes (produit, quantité, prix, catégorie)
ventes = [
    ("pomme", 5, 0.80, "fruits"),
    ("banane", 3, 0.50, "fruits"),
    ("pain", 2, 1.20, "boulangerie"),
    ("lait", 1, 0.90, "laitier"),
    ("fromage", 2, 2.50, "laitier"),
    ("pomme", 2, 0.80, "fruits"),
    ("yaourt", 4, 0.60, "laitier")
]

# Utilisation de dictionnaires pour regrouper par catégorie
ventes_par_categorie = {}
for produit, quantite, prix, categorie in ventes:
    if categorie not in ventes_par_categorie:
        ventes_par_categorie[categorie] = []
    ventes_par_categorie[categorie].append((produit, quantite, prix))

# Utilisation d'ensembles pour obtenir des produits uniques
produits_uniques = {produit for produit, _, _, _ in ventes}
print(f"Produits uniques: {produits_uniques}")  # {'pain', 'pomme', 'fromage', 'lait', 'yaourt', 'banane'}

# Utilisation de tuples pour stocker les totaux par catégorie (immuable)
totaux_par_categorie = tuple(
    (categorie, sum(quantite * prix for _, quantite, prix in produits))
    for categorie, produits in ventes_par_categorie.items()
)
print("Totaux par catégorie:", totaux_par_categorie)

# Utilisation de listes et de compréhensions pour analyser les ventes
total_par_produit = {}
for produit, quantite, prix, _ in ventes:
    if produit in total_par_produit:
        total_par_produit[produit] = (total_par_produit[produit][0] + quantite, prix)
    else:
        total_par_produit[produit] = (quantite, prix)

# Liste triée des produits par chiffre d'affaires
ca_par_produit = [(produit, quantite * prix) for produit, (quantite, prix) in total_par_produit.items()]
ca_par_produit.sort(key=lambda x: x[1], reverse=True)

print("Produits par chiffre d'affaires:")
for produit, ca in ca_par_produit:
    print(f"- {produit}: {ca:.2f}€")

Performances des structures de données

Pour des applications qui manipulent de grandes quantités de données, les performances deviennent importantes. Voici un aperçu des complexités temporelles pour les opérations courantes :

OpérationListeTupleDictionnaireEnsemble
Accès par indexO(1)O(1)N/AN/A
Accès par cléN/AN/AO(1)¹N/A
Recherche d’élémentO(n)O(n)O(1)¹O(1)¹
Ajout d’élémentO(1)²N/AO(1)¹O(1)¹
Suppression d’élémentO(n)N/AO(1)¹O(1)¹

¹ En moyenne. Dans le pire des cas (rares), ces opérations peuvent être O(n).
² L’ajout à la fin est O(1) amorti. L’insertion au milieu est O(n).

Conclusion

Les structures de données sont les blocs de construction fondamentaux de tout programme Python. Comprendre leurs caractéristiques, avantages et inconvénients vous aidera à écrire un code plus efficace et plus élégant.

Pour récapituler :

  • Les listes sont polyvalentes et modifiables, parfaites pour les collections ordonnées
  • Les tuples sont immuables et efficaces, idéaux pour les données en lecture seule
  • Les dictionnaires offrent des recherches rapides par clé, parfaits pour les associations
  • Les ensembles éliminent les doublons et permettent des opérations ensemblistes efficaces

Choisir la bonne structure pour chaque situation est une compétence qui s’améliore avec la pratique. N’hésitez pas à expérimenter avec différentes approches pour résoudre vos problèmes de données.

Dans le prochain tutoriel, nous explorerons les fonctions en Python et comment les utiliser pour organiser et réutiliser votre code efficacement.


Besoin de réviser les bases de Python ? Consultez notre tutoriel sur les bases de la syntaxe Python.

Commentaires

Les commentaires sont alimentés par GitHub Discussions

Connectez-vous avec GitHub pour participer à la discussion

Lien copié !