Python Language Liste des compréhensions


Exemple

Une compréhension de liste crée une nouvelle list en appliquant une expression à chaque élément d’une itération . La forme la plus élémentaire est:

[ <expression> for <element> in <iterable> ]

Il y a aussi une condition optionnelle "if":

[ <expression> for <element> in <iterable> if <condition> ]

Chaque <element> dans le <iterable> est branché à la <expression> si ( en option) <condition> évalue à true . Tous les résultats sont renvoyés immédiatement dans la nouvelle liste. Les expressions de générateur sont évaluées paresseusement, mais les compréhensions de liste évaluent immédiatement tout l'itérateur - une mémoire consommatrice proportionnelle à la longueur de l'itérateur.

Pour créer une list d'entiers carrés:

squares = [x * x for x in (1, 2, 3, 4)]
# squares: [1, 4, 9, 16]

L'expression for définit x sur chaque valeur à partir de (1, 2, 3, 4) . Le résultat de l'expression x * x est ajouté à une list interne. La list interne est affectée aux squares variables une fois remplie.

Outre une augmentation de la vitesse (comme expliqué ici ), une compréhension de la liste est à peu près équivalente à la suivante pour la boucle:

squares = []
for x in (1, 2, 3, 4):
    squares.append(x * x)
# squares: [1, 4, 9, 16]

L'expression appliquée à chaque élément peut être aussi complexe que nécessaire:

# Get a list of uppercase characters from a string
[s.upper() for s in "Hello World"]
# ['H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D']

# Strip off any commas from the end of strings in a list
[w.strip(',') for w in ['these,', 'words,,', 'mostly', 'have,commas,']]
# ['these', 'words', 'mostly', 'have,commas']

# Organize letters in words more reasonably - in an alphabetical order
sentence = "Beautiful is better than ugly"
["".join(sorted(word, key = lambda x: x.lower())) for word in sentence.split()]
# ['aBefiltuu', 'is', 'beertt', 'ahnt', 'gluy']

autre

else peut être utilisé dans les constructions de compréhension de liste, mais faites attention à la syntaxe. If / else clauses doivent être utilisés avant for la boucle, et non après:

# create a list of characters in apple, replacing non vowels with '*'
# Ex - 'apple' --> ['a', '*', '*', '*' ,'e']

[x for x in 'apple' if x in 'aeiou' else '*']
#SyntaxError: invalid syntax

# When using if/else together use them before the loop
[x if x in 'aeiou' else '*' for x in 'apple']
#['a', '*', '*', '*', 'e']

Notez que cela utilise une construction de langage différente, une expression conditionnelle , qui ne fait pas partie de la syntaxe de compréhension . Alors que if après le for…in fait partie des compréhensions de listes et permet de filtrer des éléments de la source itérable.


Double itération

L'ordre de la double itération [... for x in ... for y in ...] est soit naturel, soit contre-intuitif. La règle de base est de suivre un équivalent for boucle:

def foo(i):
    return i, i + 0.5

for i in range(3):
    for x in foo(i):
        yield str(x)

Cela devient:

[str(x)
    for i in range(3)
        for x in foo(i)
]

Cela peut être compressé en une seule ligne comme [str(x) for i in range(3) for x in foo(i)]


Mutation en place et autres effets secondaires

Avant d'utiliser la compréhension de liste, comprenez la différence entre les fonctions appelées pour leurs effets secondaires (fonctions mutantes ou in- situ) qui renvoient généralement None et les fonctions qui renvoient une valeur intéressante.

De nombreuses fonctions (en particulier les fonctions pures ) prennent simplement un objet et renvoient un objet. Une fonction sur place modifie l'objet existant, appelé effet secondaire . D'autres exemples incluent des opérations d'entrée et de sortie telles que l'impression.

list.sort() trie une liste sur place (ce qui signifie qu'elle modifie la liste d'origine) et renvoie la valeur None . Par conséquent, cela ne fonctionnera pas comme prévu dans une liste de compréhension:

[x.sort() for x in [[2, 1], [4, 3], [0, 1]]]
# [None, None, None]

Au lieu de cela, sorted() renvoie une list triée plutôt que de trier sur place:

[sorted(x) for x in [[2, 1], [4, 3], [0, 1]]]
# [[1, 2], [3, 4], [0, 1]]

L'utilisation de la compréhension des effets secondaires est possible, comme les fonctions d'E / S ou sur place. Pourtant, une boucle for est généralement plus lisible. Alors que cela fonctionne dans Python 3:

[print(x) for x in (1, 2, 3)]

Au lieu de cela, utilisez:

for x in (1, 2, 3):
    print(x)

Dans certaines situations, les fonctions d'effets secondaires sont adaptés à la compréhension de la liste. random.randrange() a pour effet secondaire de modifier l'état du générateur de nombres aléatoires, mais il renvoie également une valeur intéressante. En outre, next() peut être appelé sur un itérateur.

Le générateur de valeur aléatoire suivant n'est pas pur, mais il a du sens car le générateur aléatoire est réinitialisé à chaque fois que l'expression est évaluée:

from random import randrange
[randrange(1, 7) for _ in range(10)]
# [2, 3, 2, 1, 1, 5, 2, 4, 3, 5]

Les espaces dans les listes compréhensibles

Des compréhensions de listes plus compliquées peuvent atteindre une durée indésirable ou devenir moins lisibles. Bien que moins courant dans les exemples, il est possible de diviser une compréhension de liste en plusieurs lignes comme suit:

[
    x for x
    in 'foo'
    if x not in 'bar'
]