Python & AI Tutorials Logo
Programmation Python

37. Fonctions intégrées et outils utiles

Python fournit une riche collection de fonctions intégrées qui sont toujours disponibles sans avoir besoin d’importer des modules. Ces fonctions constituent la base de la programmation Python au quotidien, en vous aidant à travailler efficacement avec les données, les séquences et les collections. Dans ce chapitre, nous allons explorer les outils intégrés les plus utiles de Python et apprendre à les exploiter pour écrire du code plus propre et plus expressif.

Comprendre le système de types de Python

Avant d’examiner des fonctions intégrées spécifiques, il est utile de comprendre comment Python organise ses types de données. Cette connaissance vous aidera à prévoir quelles opérations fonctionnent avec quels types et à comprendre les messages d’erreur lorsqu’ils surviennent.

Les types de données de Python peuvent être compris selon deux perspectives complémentaires :

Hiérarchie des types : comment les types sont liés

object

Types numériques

Types de séquence

Types de mappage

Types d’ensembles

Autres

int

float

complex

Immuables

Mutables

str

tuple

range

list

dict

set

frozenset

bool

NoneType

Cela montre comment Python organise les types en familles en fonction de ce qu’ils SONT.

Vue basée sur les capacités : ce que les types peuvent faire

Pour les fonctions intégrées, ce qui compte davantage, c’est ce que les types peuvent FAIRE :

Tous les objets Python

Itérable
(peut boucler avec for)

Non itérable
(int, float, bool)

Collection
(a une longueur)

Autres itérables
(generator, iterator)

Séquence
(ordonnée, indexée)

Non ordonné
(set, dict)

str

list

tuple

range

set

dict

Capacités clés :

  • Itérable(iterable) : Peut être utilisé dans des boucles for → Fonctionne avec sum(), any(), all(), sorted()
  • Collection(collection) : Itérable avec len() → Fonctionne avec len() et l’opérateur in
  • Séquence(sequence) : Collection avec indexation → Prend en charge [index] et le slicing [start:end]

Pourquoi c’est important

Les fonctions intégrées nécessitent des capacités spécifiques :

FunctionRequiresWorks With
len()Collectionstr, list, dict, set, tuple
sum()Iterable of numberslist, tuple, set, range, generator
sorted()Iterablestr, list, dict, set, tuple
[index]Sequencestr, list, tuple, range

Comprendre ces catégories vous aide à :

  • Prévoir quelles fonctions marchent avec quels types
  • Comprendre des messages d’erreur comme « object is not iterable »
  • Savoir quand vous pouvez indexer ([0]) et quand vous ne pouvez que boucler (for)

37.1) Fonctions intégrées courantes (len, sum, min, max, abs, round)

Les fonctions intégrées les plus fréquemment utilisées de Python vous aident à effectuer des opérations courantes sur les données sans écrire de boucles ou de logique complexe. Ces fonctions sont optimisées, lisibles et constituent la base d’un code pythonique.

37.1.1) Mesurer une longueur avec len()

La fonction len() renvoie le nombre d’éléments dans une collection. Elle fonctionne avec les chaînes de caractères, les listes, les tuples, les dictionnaires, les ensembles, et tout autre type de collection.

python
# Compter les caractères dans une chaîne
message = "Hello, World!"
print(len(message))  # Output: 13
 
# Compter les éléments dans une liste
scores = [85, 92, 78, 90, 88]
print(len(scores))   # Output: 5
 
# Compter les paires clé-valeur dans un dictionnaire
student = {"name": "Bob", "age": 21, "major": "CS"}
print(len(student))  # Output: 3
 
# Compter les éléments uniques dans un ensemble
unique_ids = {101, 102, 103, 101, 102}  # Doublons supprimés
print(len(unique_ids))  # Output: 3

La fonction len() est particulièrement utile lorsque vous devez connaître la taille des données avant de les traiter :

python
# Traiter des données en fonction de leur taille
data = [12, 45, 23, 67, 89, 34]
 
if len(data) < 5:
    print("Not enough data for analysis")
else:
    print(f"Analyzing {len(data)} data points")  # Output: Analyzing 6 data points
    average = sum(data) / len(data)
    print(f"Average: {average}")  # Output: Average: 45.0

37.1.2) Calculer des totaux avec sum()

La fonction sum() additionne tous les nombres d’un itérable. C’est bien plus propre que d’écrire une boucle pour accumuler des valeurs.

python
# Additionner une liste de nombres
prices = [19.99, 24.50, 15.75, 32.00]
total = sum(prices)
print(f"Total: ${total}")  # Output: Total: $92.24
 
# Additionner un tuple
daily_steps = (8500, 10200, 7800, 9500, 11000)
weekly_total = sum(daily_steps)
print(f"Total steps this week: {weekly_total}")  # Output: Total steps this week: 47000
 
# Additionner un range
total_1_to_100 = sum(range(1, 101))
print(total_1_to_100)  # Output: 5050

Un exemple pratique combinant sum() et len() pour calculer des moyennes :

python
# Calculer la moyenne d’un score de test
test_scores = [88, 92, 79, 85, 90, 87]
 
total_score = sum(test_scores)
num_tests = len(test_scores)
average_score = total_score / num_tests
 
print(f"Average score: {average_score:.1f}")  # Output: Average score: 86.8

Limitation importante : sum() ne fonctionne qu’avec des nombres. Vous ne pouvez pas l’utiliser pour concaténer des chaînes ou combiner des listes :

python
# Ceci déclenche TypeError
words = ["Hello", " ", "World"]
# sentence = sum(words)  # TypeError: unsupported operand type(s)

37.1.3) Trouver des extrêmes avec min() et max()

Les fonctions min() et max() trouvent les plus petites et plus grandes valeurs dans un itérable. Elles fonctionnent avec les nombres, les chaînes et tout objet pouvant être comparé.

python
# Trouver le minimum et le maximum de nombres
temperatures = [72, 68, 75, 70, 73, 69]
coldest = min(temperatures)
warmest = max(temperatures)
print(f"Temperature range: {coldest}°F to {warmest}°F")
# Output: Temperature range: 68°F to 75°F
 
# Trouver le minimum et le maximum de chaînes (alphabétiquement)
names = ["Zoe", "Alice", "Bob", "Charlie"]
first_alphabetically = min(names)
last_alphabetically = max(names)
print(f"First: {first_alphabetically}, Last: {last_alphabetically}")
# Output: First: Alice, Last: Zoe

Vous pouvez aussi passer plusieurs arguments directement au lieu d’une collection :

python
# Comparer des valeurs individuelles
lowest = min(45, 23, 67, 12, 89)
highest = max(45, 23, 67, 12, 89)
print(f"Lowest: {lowest}, Highest: {highest}")
# Output: Lowest: 12, Highest: 89
 
# Utile pour comparer quelques valeurs spécifiques
price1 = 19.99
price2 = 24.50
price3 = 15.75
cheapest = min(price1, price2, price3)
print(f"Cheapest option: ${cheapest}")  # Output: Cheapest option: $15.75

37.1.4) Obtenir des valeurs absolues avec abs()

La fonction abs() renvoie la valeur absolue d’un nombre — sa distance à zéro, toujours positive. C’est utile lorsque vous vous intéressez à la magnitude mais pas à la direction.

python
# Valeur absolue de nombres négatifs
print(abs(-42))      # Output: 42
print(abs(-3.14))    # Output: 3.14
 
# Valeur absolue de nombres positifs (inchangée)
print(abs(42))       # Output: 42
print(abs(3.14))     # Output: 3.14
 
# Valeur absolue de zéro
print(abs(0))        # Output: 0

Un cas d’usage courant consiste à calculer des différences où la direction n’a pas d’importance :

python
# Calculer un changement de température (magnitude uniquement)
morning_temp = 65
evening_temp = 72
temperature_change = abs(evening_temp - morning_temp)
print(f"Temperature changed by {temperature_change}°F")
# Output: Temperature changed by 7°F

37.1.5) Arrondir des nombres avec round()

La fonction round() arrondit un nombre à un nombre spécifié de décimales. Sans second argument, elle arrondit à l’entier le plus proche.

python
# Arrondir à l’entier le plus proche
print(round(3.7))     # Output: 4
print(round(3.2))     # Output: 3
print(round(3.5))     # Output: 4
print(round(4.5))     # Output: 4  (arrondit vers le nombre pair le plus proche)
 
# Arrondir à un nombre précis de décimales
price = 19.876
print(round(price, 2))  # Output: 19.88  (2 decimal places)
print(round(price, 1))  # Output: 19.9   (1 decimal place)
 
# Arrondir à des décimales négatives (arrondit aux dizaines, centaines, etc.)
population = 1234567
print(round(population, -3))  # Output: 1235000  (nearest thousand)
print(round(population, -4))  # Output: 1230000  (nearest ten thousand)

Remarque sur les valeurs à mi-chemin : Lorsqu’on arrondit un nombre qui se trouve exactement à mi-chemin entre deux entiers, Python applique une règle spéciale. Par exemple, 2.5 est exactement à mi-chemin entre 2 et 3. Vous pourriez vous attendre à ce qu’il arrondisse vers le haut à 3, mais Python arrondit vers le voisin qui est un nombre pair — dans ce cas, 2.

Cela s’appelle « banker's rounding » ou « round half to even ». Cela fait partie du standard IEEE 754 et aide à réduire le biais sur de nombreuses opérations d’arrondi.

python
# Les valeurs à mi-chemin sont arrondies vers le nombre pair le plus proche
print(round(0.5))   # Output: 0 (0 is even)
print(round(1.5))   # Output: 2 (2 is even)
print(round(2.5))   # Output: 2 (2 is even)
print(round(3.5))   # Output: 4 (4 is even)
print(round(4.5))   # Output: 4 (4 is even)

37.2) Énumérer des séquences avec enumerate()

Lorsque vous bouclez sur une séquence, vous avez souvent besoin à la fois de l’élément et de sa position. La fonction enumerate() fournit les deux, éliminant le besoin de variables de compteur manuelles.

37.2.1) Le problème des compteurs manuels

Avant d’apprendre enumerate(), les programmeurs utilisent souvent une variable compteur pour suivre la position :

python
# Approche avec compteur manuel (fonctionne mais pas idéale)
fruits = ["apple", "banana", "cherry", "date"]
index = 0
 
for fruit in fruits:
    print(f"{index}: {fruit}")
    index += 1
# Output:
# 0: apple
# 1: banana
# 2: cherry
# 3: date

Cette approche a plusieurs inconvénients :

  • Variable supplémentaire à gérer (index)
  • Facile d’oublier d’incrémenter le compteur

37.2.2) Utiliser enumerate() pour la position et la valeur

La fonction enumerate() résout ce problème élégamment. Elle prend un itérable et renvoie des paires (index, élément) :

python
# Utiliser enumerate() - plus propre et plus pythonique
fruits = ["apple", "banana", "cherry", "date"]
 
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
# Output:
# 0: apple
# 1: banana
# 2: cherry
# 3: date

La syntaxe for index, fruit in enumerate(fruits) utilise le dépaquetage de tuple (comme nous l’avons appris au Chapitre 15). À chaque itération, enumerate() fournit un tuple comme (0, "apple"), qui est dépaqueté dans les variables index et fruit.

Voici ce que enumerate() produit réellement :

python
# Voir directement la sortie de enumerate
fruits = ["apple", "banana", "cherry"]
enumerated = list(enumerate(fruits))
print(enumerated)
# Output: [(0, 'apple'), (1, 'banana'), (2, 'cherry')]

37.2.3) Démarrer l’énumération à partir d’un nombre différent

Par défaut, enumerate() commence à compter à partir de 0. Vous pouvez spécifier un nombre de départ différent avec le paramètre start :

python
# Commencer à compter à partir de 1 (utile pour l’affichage)
tasks = ["Write code", "Test code", "Deploy code"]
 
for number, task in enumerate(tasks, start=1):
    print(f"Step {number}: {task}")
# Output:
# Step 1: Write code
# Step 2: Test code
# Step 3: Deploy code

C’est particulièrement utile lorsque vous affichez des listes numérotées aux utilisateurs, qui s’attendent généralement à ce que le comptage commence à 1 :

python
# Menu avec options numérotées
menu_items = ["New Game", "Load Game", "Settings", "Quit"]
 
print("Main Menu:")
for number, item in enumerate(menu_items, start=1):
    print(f"{number}. {item}")
# Output:
# Main Menu:
# 1. New Game
# 2. Load Game
# 3. Settings
# 4. Quit

37.2.4) enumerate() avec des chaînes et d’autres itérables

La fonction enumerate() fonctionne avec n’importe quel itérable, pas seulement les listes :

python
# Énumérer les caractères d’une chaîne
word = "Python"
 
for position, letter in enumerate(word):
    print(f"Letter {position}: {letter}")
# Output:
# Letter 0: P
# Letter 1: y
# Letter 2: t
# Letter 3: h
# Letter 4: o
# Letter 5: n
 
# Énumérer un tuple
coordinates = (10, 20, 30, 40)
 
for index, value in enumerate(coordinates):
    print(f"Coordinate {index}: {value}")
# Output:
# Coordinate 0: 10
# Coordinate 1: 20
# Coordinate 2: 30
# Coordinate 3: 40

La fonction enumerate() rend le code plus lisible et moins sujet aux erreurs. Chaque fois que vous avez besoin à la fois de la position et de la valeur dans une boucle, utilisez enumerate() plutôt que de gérer un compteur manuellement.

37.3) Combiner des séquences avec zip()

La fonction zip() combine plusieurs itérables élément par élément, en créant des paires (ou des tuples) d’éléments correspondants. C’est extrêmement utile lorsque vous devez traiter simultanément des données liées provenant de séquences séparées.

37.3.1) Comprendre comment zip() fonctionne

La fonction zip() prend deux itérables ou plus et renvoie un itérateur de tuples, où chaque tuple contient un élément de chaque itérable d’entrée :

python
# Combiner deux listes
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
 
combined = list(zip(names, ages))
print(combined)
# Output: [('Alice', 25), ('Bob', 30), ('Charlie', 35)]

Le nom « zip » vient de la fermeture éclair sur les vêtements — elle combine deux côtés séparés en une structure jointe, élément par élément.

Voici une représentation visuelle de la façon dont zip() associe les éléments :

names
['Alice', 'Bob', 'Charlie']

zip()

ages
[25, 30, 35]

[('Alice', 25),
('Bob', 30),
('Charlie', 35)]

37.3.2) Utiliser zip() dans des boucles

L’usage le plus courant de zip() est dans les boucles for, lorsque vous devez itérer sur plusieurs séquences simultanément :

python
# Traiter des données parallèles
students = ["Alice", "Bob", "Charlie", "Diana"]
scores = [92, 85, 88, 95]
 
for student, score in zip(students, scores):
    print(f"{student} scored {score}")
# Output:
# Alice scored 92
# Bob scored 85
# Charlie scored 88
# Diana scored 95

C’est beaucoup plus propre que d’utiliser des indices :

python
# Sans zip() - plus complexe et plus sujet aux erreurs
students = ["Alice", "Bob", "Charlie", "Diana"]
scores = [92, 85, 88, 95]
 
for i in range(len(students)):
    print(f"{students[i]} scored {scores[i]}")
# Same output, but more code and potential for index errors

37.3.3) Gérer des séquences de longueurs différentes

Lorsque les séquences d’entrée ont des longueurs différentes, zip() s’arrête lorsque la séquence la plus courte est épuisée :

python
# Séquences de longueur inégale
names = ["Alice", "Bob", "Charlie", "Diana"]
ages = [25, 30]  # Seulement 2 âges
 
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")
# Output:
# Alice is 25 years old
# Bob is 30 years old
# (Charlie and Diana are not processed)

Ce comportement évite les erreurs, mais peut entraîner une perte silencieuse de données si vous n’y prenez pas garde. Vérifiez toujours que vos séquences ont les longueurs attendues :

python
# Vérifier les différences de longueur
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30]
 
if len(names) != len(ages):
    print(f"Warning: {len(names)} names but {len(ages)} ages")
    print("Only processing the first", min(len(names), len(ages)), "entries")
    # Output: Warning: 3 names but 2 ages
    # Output: Only processing the first 2 entries
 
# Continuer avec zip() - il s’arrêtera à la plus courte
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")

37.3.4) Zipper plus de deux séquences

La fonction zip() peut combiner n’importe quel nombre d’itérables :

python
# Combiner trois séquences
products = ["Laptop", "Mouse", "Keyboard"]
prices = [999.99, 24.99, 79.99]
quantities = [5, 20, 15]
 
print("Inventory Report:")
for product, price, quantity in zip(products, prices, quantities):
    total_value = price * quantity
    print(f"{product}: ${price} × {quantity} = ${total_value:.2f}")
# Output:
# Inventory Report:
# Laptop: $999.99 × 5 = $4999.95
# Mouse: $24.99 × 20 = $499.80
# Keyboard: $79.99 × 15 = $1199.85

37.3.5) Créer des dictionnaires avec zip()

Un motif puissant consiste à utiliser zip() pour créer des dictionnaires à partir de séquences de clés et de valeurs séparées :

python
# Créer un dictionnaire à partir de deux listes
keys = ["name", "age", "city"]
values = ["Alice", 25, "Boston"]
 
person = dict(zip(keys, values))
print(person)
# Output: {'name': 'Alice', 'age': 25, 'city': 'Boston'}

37.4) Agrégation booléenne avec any() et all()

Les fonctions any() et all() testent des conditions sur des itérables entiers, en renvoyant un seul résultat booléen. Ce sont des outils puissants pour la validation et la prise de décision à partir de plusieurs conditions.

37.4.1) Comprendre any() : True si au moins un élément est True

La fonction any() renvoie True si au moins un élément dans un itérable est truthy (évalué à True). Si tous les éléments sont falsy, elle renvoie False :

python
# Exemples de base avec any()
print(any([True, False, False]))   # Output: True  (at least one True)
print(any([False, False, False]))  # Output: False (all False)
print(any([False, True, True]))    # Output: True  (multiple True values)
 
# Itérables vides
print(any([]))  # Output: False (no elements to be True)

La fonction any() utilise les règles de truthiness de Python (comme nous l’avons appris au Chapitre 7). Les nombres non nuls, les chaînes non vides et les collections non vides sont truthy :

python
# any() avec différentes valeurs truthy/falsy
print(any([0, 0, 1]))           # Output: True  (1 is truthy)
print(any([0, 0, 0]))           # Output: False (all zeros are falsy)
print(any(["", "", "text"]))    # Output: True  ("text" is truthy)
print(any(["", "", ""]))        # Output: False (empty strings are falsy)

37.4.2) Utilisations pratiques de any()

Exemple : vérifier si une condition est satisfaite

python
# Vérifier si un score est insuffisant (inférieur à 60)
scores = [75, 82, 55, 90, 88]
has_failing_grade = any(score < 60 for score in scores)
 
if has_failing_grade:
    print("Warning: At least one failing grade")
    # Output: Warning: At least one failing grade
else:
    print("All grades are passing")

37.4.3) Comprendre all() : True seulement si tous les éléments sont True

La fonction all() renvoie True uniquement si tous les éléments d’un itérable sont truthy. Si un seul élément est falsy, elle renvoie False :

python
# Exemples de base avec all()
print(all([True, True, True]))    # Output: True  (all True)
print(all([True, False, True]))   # Output: False (one False)
print(all([True, True, False]))   # Output: False (one False)
 
# Itérables vides
print(all([]))  # Output: True (vacuous truth - no False elements)

Le comportement avec des itérables vides peut sembler surprenant : all([]) renvoie True. Cela s’appelle la vérité vacante — l’énoncé « tous les éléments sont True » est techniquement vrai lorsqu’il n’y a aucun élément pour le contredire.

python
# all() avec différentes valeurs truthy/falsy
print(all([1, 2, 3]))           # Output: True  (all non-zero)
print(all([1, 0, 3]))           # Output: False (0 is falsy)
print(all(["a", "b", "c"]))     # Output: True  (all non-empty)
print(all(["a", "", "c"]))      # Output: False (empty string is falsy)

37.4.4) Utilisations pratiques de all()

Exemple : valider que toutes les conditions sont remplies

python
# Vérifier si tous les scores sont suffisants (60 ou plus)
scores = [75, 82, 68, 90, 88]
all_passing = all(score >= 60 for score in scores)
 
if all_passing:
    print("Congratulations! All grades are passing")
    # Output: Congratulations! All grades are passing
else:
    print("Some grades need improvement")

37.4.5) Évaluation en court-circuit dans any() et all()

any() et all() utilisent tous deux l’évaluation en court-circuit (comme nous l’avons appris au Chapitre 9). Ils arrêtent de vérifier dès que le résultat est déterminé :

python
# Fonction qui affiche lors de l’appel (pour montrer l’exécution)
def is_positive(n):
    print(f"Checking {n}")
    return n > 0
 
# any() s’arrête au premier True
print("Testing any():")
numbers = [0, 0, 1, 2, 3]
result = any(is_positive(n) for n in numbers)
# Output:
# Testing any():
# Checking 0
# Checking 0
# Checking 1
# (Stops here - doesn't check 2 or 3)
print(f"Result: {result}")  # Output: Result: True
 
print("\nTesting all():")
numbers = [1, 2, 0, 3, 4]
result = all(is_positive(n) for n in numbers)
# Output:
# Testing all():
# Checking 1
# Checking 2
# Checking 0
# (Stops here - doesn't check 3 or 4)
print(f"Result: {result}")  # Output: Result: False

Cela rend any() et all() efficaces — ils ne perdent pas de temps à vérifier des éléments après que le résultat a été déterminé.

37.5) Trier avec sorted() et des clés personnalisées

La fonction sorted() crée une nouvelle liste triée à partir de n’importe quel itérable. Contrairement à la méthode .sort() (qui ne fonctionne que sur les listes et les modifie sur place), sorted() fonctionne avec tout itérable et renvoie toujours une nouvelle liste.

37.5.1) Tri de base avec sorted()

La fonction sorted() organise les éléments dans l’ordre croissant par défaut :

python
# Trier des nombres
numbers = [42, 17, 93, 8, 55]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # Output: [8, 17, 42, 55, 93]
 
# La liste d’origine est inchangée
print(numbers)  # Output: [42, 17, 93, 8, 55]
 
# Trier des chaînes (alphabétiquement)
names = ["Charlie", "Alice", "Bob", "Diana"]
sorted_names = sorted(names)
print(sorted_names)  # Output: ['Alice', 'Bob', 'Charlie', 'Diana']

La fonction sorted() fonctionne avec n’importe quel itérable, pas seulement les listes :

python
# Trier un tuple (renvoie une liste)
coordinates = (5, 2, 8, 1, 9)
sorted_coords = sorted(coordinates)
print(sorted_coords)  # Output: [1, 2, 5, 8, 9]
 
# Trier une chaîne (renvoie une liste de caractères)
word = "python"
sorted_letters = sorted(word)
print(sorted_letters)  # Output: ['h', 'n', 'o', 'p', 't', 'y']
 
# Trier un ensemble (renvoie une liste triée)
unique_numbers = {5, 8, 2, 1}
sorted_unique = sorted(unique_numbers)
print(sorted_unique)  # Output: [1, 2, 5, 8]

37.5.2) Tri inversé

Utilisez le paramètre reverse=True pour trier dans l’ordre décroissant :

python
# Ordre décroissant pour des nombres
scores = [85, 92, 78, 95, 88]
highest_first = sorted(scores, reverse=True)
print(highest_first)  # Output: [95, 92, 88, 85, 78]
 
# Ordre décroissant pour des chaînes (inverse alphabétique)
names = ["Charlie", "Alice", "Bob", "Diana"]
reverse_alpha = sorted(names, reverse=True)
print(reverse_alpha)  # Output: ['Diana', 'Charlie', 'Bob', 'Alice']

37.5.3) Comprendre le paramètre key

Le paramètre key est ce qui rend sorted() vraiment puissant. Il transforme la manière dont Python compare les éléments pendant le tri.

Qu’est-ce que le paramètre key ?

Le paramètre key accepte une fonction(function). Python appelle cette fonction sur chaque élément pour en extraire une « clé de comparaison », puis trie en se basant sur ces clés plutôt que sur les éléments d’origine.

Comment cela fonctionne étape par étape :

  1. Python appelle la fonction key sur chaque élément
  2. Python collecte toutes les clés
  3. Python trie en comparant ces clés
  4. Python renvoie les éléments d’origine dans le nouvel ordre
python
# Exemple : trier par longueur
words = ["python", "is", "awesome"]
 
# Étape 1 : Python appelle len() sur chaque mot
# len("python")  → 6
# len("is")      → 2
# len("awesome") → 7
 
# Étape 2 : Python a ces clés : [6, 2, 7]
 
# Étape 3 : Python trie les clés : [2, 6, 7]
 
# Étape 4 : Python renvoie les mots dans cet ordre : ["is", "python", "awesome"]
 
result = sorted(words, key=len)
print(result)  # Output: ['is', 'python', 'awesome']

Visualiser la fonction key :

Original:
['python', 'is', 'awesome']

Appliquer key=len

Clés:
[6, 2, 7]

Trier les clés

Clés triées:
[2, 6, 7]

Renvoyer les éléments:
['is', 'python', 'awesome']

Que peut être une fonction key ?

La fonction key doit :

  • Accepter un argument (l’élément trié)
  • Renvoyer une valeur que Python peut comparer (nombres, chaînes, tuples, etc.)
python
# Les fonctions intégrées fonctionnent très bien
sorted(numbers, key=abs)        # Trier par valeur absolue
sorted(words, key=len)          # Trier par longueur
sorted(names, key=str.lower)    # Trier sans tenir compte de la casse
 
# Vos propres fonctions
def first_letter(word):
    return word[0]
 
sorted(words, key=first_letter)  # Trier par première lettre
 
# Fonctions lambda (Chapitre 23)
sorted(words, key=lambda w: w[-1])  # Trier par dernière lettre

Important : la fonction key est appelée une fois par élément

python
# Montrer quand la fonction key est appelée
def show_key(word):
    print(f"Getting key for: {word}")
    return len(word)
 
words = ["cat", "elephant", "dog"]
result = sorted(words, key=show_key)
# Output:
# Getting key for: cat
# Getting key for: elephant
# Getting key for: dog
 
print(result)  # Output: ['cat', 'dog', 'elephant']

Important : la fonction key est appelée une fois par élément

Remarquez que show_key est appelée exactement une fois pour chaque mot, et non de façon répétée pendant les comparaisons. Python est efficace : il extrait toutes les clés d’abord, les met en cache, puis trie en utilisant les clés mises en cache.

Pensez à key comme à la réponse à : « Quel aspect dois-je comparer ? »

  • key=len → « Comparer par longueur »
  • key=abs → « Comparer par valeur absolue »
  • key=str.lower → « Comparer comme si tout était en minuscules »
  • key=lambda x: x[1] → « Comparer par le deuxième élément »

Le paramètre key vous permet de trier selon n’importe quelle propriété de vos éléments, ce qui rend sorted() incroyablement polyvalent.

37.5.4) Trier avec des fonctions intégrées comme clés

Les fonctions intégrées de Python font d’excellentes fonctions key :

python
# Trier par valeur absolue
numbers = [-5, 2, -8, 1, -3, 7]
sorted_by_magnitude = sorted(numbers, key=abs)
print(sorted_by_magnitude)  # Output: [1, 2, -3, -5, 7, -8]
 
# Trier des chaînes sans tenir compte de la casse
names = ["alice", "Bob", "CHARLIE", "diana"]
sorted_case_insensitive = sorted(names, key=str.lower)
print(sorted_case_insensitive)  # Output: ['alice', 'Bob', 'CHARLIE', 'diana']

37.5.5) Trier des structures de données complexes

Lors du tri de listes de tuples ou de listes, vous pouvez utiliser l’indexation pour indiquer par quel élément trier :

python
# Trier des tuples par le deuxième élément
students = [
    ("Alice", 92),
    ("Bob", 85),
    ("Charlie", 88),
    ("Diana", 95)
]
 
# Trier par score (deuxième élément)
by_score = sorted(students, key=lambda student: student[1])
print(by_score)
# Output: [('Bob', 85), ('Charlie', 88), ('Alice', 92), ('Diana', 95)]
 
# Trier par score décroissant
by_score_desc = sorted(students, key=lambda student: student[1], reverse=True)
print(by_score_desc)
# Output: [('Diana', 95), ('Alice', 92), ('Charlie', 88), ('Bob', 85)]

Remarque : Nous utilisons lambda ici (comme nous l’avons appris au Chapitre 23). Une lambda est une petite fonction anonyme. L’expression lambda student: student[1] crée une fonction qui prend un tuple étudiant et renvoie son deuxième élément (le score).

37.5.6) Tri à plusieurs niveaux

Vous pouvez trier selon plusieurs critères en renvoyant un tuple depuis la fonction key. Python compare les tuples élément par élément, de gauche à droite :

Comment fonctionne la comparaison de tuples :

Lorsque Python compare deux tuples, il suit ces règles :

  1. Comparer les premiers éléments. S’ils sont différents, la comparaison est terminée.
  2. Si les premiers éléments sont égaux, comparer les deuxièmes éléments.
  3. Si les deuxièmes éléments sont égaux, comparer les troisièmes éléments.
  4. Continuer jusqu’à trouver une différence ou jusqu’à épuisement des éléments.
python
# Exemples de comparaison de tuples
print((1, 'a') < (2, 'z'))   # Output: True  (1 < 2, so True immediately)
print((1, 'z') < (1, 'a'))   # Output: False (1 == 1, so compare 'z' < 'a')
print((1, 'a') < (1, 'a'))   # Output: False (both tuples are equal)
print((1, 2, 9) < (1, 3, 1)) # Output: True  (1 == 1, then 2 < 3)

Cela rend les tuples parfaits pour un tri à plusieurs niveaux — Python gère automatiquement la logique « comparer le premier critère, puis le deuxième, puis le troisième » pour vous :

python
# Trier selon plusieurs critères
students = [
    ("Alice", "Smith", 92),
    ("Bob", "Jones", 85),
    ("Alice", "Brown", 88),
    ("Charlie", "Smith", 85)
]
 
# Trier par prénom, puis par nom
by_name = sorted(students, key=lambda s: (s[0], s[1]))
print("By name:")
for student in by_name:
    print(f"  {student}")
# Output:
# By name:
#   ('Alice', 'Brown', 88)
#   ('Alice', 'Smith', 92)
#   ('Bob', 'Jones', 85)
#   ('Charlie', 'Smith', 85)
 
# Trier par score décroissant, puis par prénom croissant
by_score_then_name = sorted(students, key=lambda s: (-s[2], s[0]))
print("\nBy score (high to low), then name:")
for student in by_score_then_name:
    print(f"  {student}")
# Output:
# By score (high to low), then name:
#   ('Alice', 'Smith', 92)
#   ('Alice', 'Brown', 88)
#   ('Bob', 'Jones', 85)
#   ('Charlie', 'Smith', 85)

Remarque : Pour trier un critère en décroissant et un autre en croissant, nous nions la valeur numérique (-s[2]). Cela fonctionne parce que la négation inverse l’ordre de tri pour les nombres. Dans l’exemple ci-dessus, -s[2] trie les scores du plus grand au plus petit, tandis que s[0] trie les prénoms de A à Z.

37.5.7) Utiliser des fonctions utilitaires pour des clés complexes

Lorsque la logique de tri devient complexe, définir une fonction utilitaire rend le code plus lisible et plus facile à maintenir. Vous pouvez ensuite utiliser cette fonction utilitaire dans votre fonction key.

Exemple : trier des fichiers par extension

Supposons que vous vouliez regrouper les fichiers par leur extension (.csv, .jpg, .pdf, etc.), et au sein de chaque groupe, trier alphabétiquement par nom de fichier. La fonction key doit extraire l’extension du fichier, ce qui nécessite une manipulation de chaînes.

python
# Trier les fichiers par extension, puis par nom
files = [
    "report.pdf",
    "data.csv",
    "image.jpg",
    "notes.txt",
    "backup.csv",
    "photo.jpg"
]
 
# Extraire l’extension pour le tri
def get_extension(filename):
    """Extraire l’extension de fichier à partir d’un nom de fichier."""
    return filename.split(".")[-1]  # Découper sur "." et prendre la dernière partie
 
# Utiliser la fonction utilitaire dans la clé
sorted_files = sorted(files, key=lambda f: (get_extension(f), f))
print("Files sorted by extension, then name:")
for file in sorted_files:
    print(f"  {file}")
# Output:
# Files sorted by extension, then name:
#   backup.csv      # csv files first (alphabetically)
#   data.csv        # csv files first (alphabetically)
#   image.jpg       # jpg files next
#   photo.jpg       # jpg files next
#   report.pdf      # pdf files next
#   notes.txt       # txt files last

Comment cela fonctionne :

  1. La fonction key lambda f: (get_extension(f), f) renvoie un tuple pour chaque nom de fichier
  2. Pour "report.pdf", elle renvoie ("pdf", "report.pdf")
  3. Pour "data.csv", elle renvoie ("csv", "data.csv")
  4. Python trie par le premier élément du tuple (extension), puis par le second élément (nom de fichier complet)
  5. Cela regroupe les fichiers par extension et trie alphabétiquement au sein de chaque groupe

Pourquoi utiliser une fonction utilitaire ?

Comparez la lisibilité :

python
# Sans fonction utilitaire - plus difficile à comprendre
sorted_files = sorted(files, key=lambda f: (f.split(".")[-1], f))
 
# Avec fonction utilitaire - intention plus claire
sorted_files = sorted(files, key=lambda f: (get_extension(f), f))

La fonction utilitaire rend votre code auto-documenté. Toute personne lisant get_extension(f) comprend immédiatement ce qui se passe, tandis que f.split(".")[-1] demande une analyse mentale.

37.5.8) sorted() vs .sort() : quand utiliser chacun

Python propose deux façons de trier :

  1. sorted() - Fonction qui renvoie une nouvelle liste triée
  2. .sort() - Méthode de liste qui trie sur place
python
# sorted() - crée une nouvelle liste, l’originale est inchangée
numbers = [3, 1, 4, 1, 5]
sorted_numbers = sorted(numbers)
print(f"Original: {numbers}")        # Output: Original: [3, 1, 4, 1, 5]
print(f"Sorted: {sorted_numbers}")   # Output: Sorted: [1, 1, 3, 4, 5]
 
# .sort() - modifie la liste sur place, renvoie None
numbers = [3, 1, 4, 1, 5]
result = numbers.sort()
print(f"Modified: {numbers}")        # Output: Modified: [1, 1, 3, 4, 5]
print(f"Return value: {result}")     # Output: Return value: None

Quand utiliser sorted() :

  • Vous devez conserver l’ordre original
  • Vous triez autre chose qu’une liste (tuple, chaîne, ensemble, etc.)
  • Vous voulez trier et affecter en une seule expression

Quand utiliser .sort() :

  • Vous avez une liste et vous n’avez pas besoin de l’ordre original
  • Vous voulez économiser de la mémoire (aucune nouvelle liste créée)
  • Vous triez une grande liste sur place pour l’efficacité

La fonction sorted() est l’un des outils les plus polyvalents de Python. Combinée au paramètre key, elle peut gérer pratiquement n’importe quel besoin de tri, du simple ordre numérique aux tris complexes multi-critères de structures de données imbriquées.


Ce chapitre vous a doté des fonctions intégrées et outils essentiels de Python. Vous avez appris à :

  • Comprendre la hiérarchie des types de Python et prévoir quelles opérations fonctionnent avec quels types
  • Utiliser des fonctions fondamentales comme len(), sum(), min(), max(), abs() et round() pour des opérations courantes
  • Itérer avec des informations de position en utilisant enumerate()
  • Traiter simultanément des séquences parallèles avec zip()
  • Prendre des décisions sur des collections avec any() et all()
  • Trier les données de manière flexible avec sorted() et des fonctions key personnalisées

Ces outils constituent la base d’un code Python idiomatique. Ils sont efficaces, lisibles et gèrent correctement les cas limites. Au fil de votre progression, vous vous surprendrez à utiliser ces fonctions constamment — ce sont les briques de base qui rendent le code Python élégant et expressif.

Dans le prochain chapitre, nous explorerons les décorateurs (decorators), qui vous permettent de modifier et d’améliorer le comportement des fonctions de manière puissante, en s’appuyant sur les concepts de fonctions de première classe que nous avons appris au Chapitre 23.


© 2025. Primesoft Co., Ltd.
support@primesoft.ai