Les compréhensions de listes sont un moyen concis de créer des listes à partir d'objets itérables existants à l'aide d'une syntaxe courte :
squares = [x**2 for x in range(10)]
Cette expression est équivalente à :
squares = [] for x in range(10): squares.append(x**2)
Les compréhensions de listes ont plusieurs avantages :
evens = [x for x in range(10) if x % 2 == 0] ;L'analogie avec map() :
def f(x): return x**2 squares = list(map(f, range(10)))
map est plus rapide sur de grandes données, s'il utilise une fonction déjà existante en C, et convient pour appliquer une fonction à tous les éléments. La compréhension de listes est destinée à des expressions, pas uniquement à des fonctions prêtes à l'emploi. La boucle for est plus flexible, mais plus encombrante.
Pourquoi, dans une expression telle que
[x for x in range(10)], la variable x se retrouve-t-elle accessible en dehors de l'expression en Python2, mais pas en Python3 ?
Réponse : En Python2, la variable de boucle (x) conserve sa valeur après l'exécution de la compréhension de listes. En Python3, elle est "isolée" et n'est pas accessible en dehors de la liste, ce qui empêche des effets secondaires indésirables.
Exemple :
# Python 2.x: [x for x in range(3)] print(x) # x == 2 # Python 3.x: [x for x in range(3)] print(x) # NameError: name 'x' is not defined
Histoire 1
Un développeur sur un grand projet voulait filtrer et créer une nouvelle liste via une compréhension de listes :
my_list = [item.transform() for item in data if item.is_valid()]
Mais l'opération item.transform() déclenchait une erreur lorsque item.is_valid() retournait False. Pourtant, la fonction de vérification était écrite avec un effet secondaire potentiel, ce qui a finalement brisé certaines parties du code avec des effets secondaires de manière non évidente.
Histoire 2
Dans le cadre d'une migration de Python2 à Python3, un développeur était convaincu que la variable de boucle resterait accessible :
[x for x in range(5)] print(x) # S'attendait à obtenir 4, mais a reçu NameError.
Cela a causé un bogue dans la logique cyclique, où la variable devait rester nécessaire en dehors de la compréhension.
Histoire 3
Utilisation de compréhensions de listes imbriquées sans indiquer explicitement les niveaux :
def flatten(matrix): return [cell for row in matrix for cell in row]
Les débutants rencontrent souvent des erreurs à cause d'un ordre d'itération incorrect (par exemple, [cell for cell in row for row in matrix] ou d'un enchaînement excessif), ce qui conduit à un résultat incorrect — une liste unidimensionnelle au lieu de bidimensionnelle ou inversement.