web-dev-qa-db-fra.com

python liste compréhension double pour

vec = [[1,2,3], [4,5,6], [7,8,9]]
print [num for elem in vec for num in elem]      <----- this

>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]

Cela me trompe.
Je comprends que elem est la liste à l'intérieur de la liste de for elem in vic
Je ne comprends pas très bien l'utilisation de num et for num in elem au début et à la fin.

Comment python interprète-t-il cela?
À quel ordre il ressemble?

49
ealeon

Permet de le décomposer.

Une simple compréhension de liste:

[x for x in collection]

Ceci est facile à comprendre si nous le divisons en plusieurs parties: [A for B in C]

  • A est l'élément qui sera dans la liste résultante
  • B est chaque élément de la collection C
  • C est la collection elle-même.

De cette façon, on pourrait écrire:

[x.lower() for x in words]

Afin de convertir tous les mots d'une liste en minuscules.


C'est lorsque nous compliquons cela avec une autre liste comme ceci:

[x for y in collection for x in y] # [A for B in C for D in E]

Ici, quelque chose de spécial se produit. Nous voulons que notre liste finale comprenne A éléments, et A éléments se trouvent dans B éléments, nous devons donc le dire à la liste-compréhension.

  • A est l'élément qui sera dans la liste résultante
  • B est chaque élément de la collection C
  • C est la collection elle-même
  • D est chaque élément de la collection E (dans ce cas, également A)
  • E est une autre collection (dans ce cas, B)

Cette logique est similaire à la boucle normale:

for y in collection:     #      for B in C:
    for x in y:          #          for D in E: (in this case: for A in B)
        # receive x      #              # receive A

Pour développer cela et donner un excellent exemple + une explication, imaginez qu'il y a un train.

Le moteur du train (l'avant) sera toujours là (résultat de la compréhension de la liste)

Ensuite, il y a un certain nombre de wagons, chaque wagon est sous la forme: for x in y

Une compréhension de la liste pourrait ressembler à ceci:

[z for b in a for c in b for d in c ... for z in y]

Ce serait comme avoir cette boucle for régulière:

for b in a:
    for c in b:
        for d in c:
            ...
                for z in y:
                    # have z

En d'autres termes, au lieu de descendre d'une ligne et de mettre en retrait, dans une compréhension de liste, vous ajoutez simplement la boucle suivante à la fin.

Pour revenir à l'analogie du train:

Engine - Car - Car - Car ... Tail

Quelle est la queue? La queue est une chose spéciale dans les listes de compréhension. Vous n'en avez pas besoin , mais si vous avez une queue, la queue est une condition, regardez cet exemple:

[line for line in file if not line.startswith('#')] 

Cela vous donnerait toutes les lignes d'un fichier tant que la ligne ne commence pas par un hashtag (#), d'autres sont simplement ignorés.

L'astuce pour utiliser la "queue" du train est qu'elle est vérifiée pour vrai/faux en même temps que vous avez votre "moteur" ou "résultat" final de toutes les boucles, l'exemple ci-dessus dans une boucle régulière ressemblerait à ceci:

for line in file:
    if not line.startswith('#'):
        # have line

veuillez noter: Bien que dans mon analogie avec un train, il n'y ait qu'une "queue" à la fin du train, la condition ou la "queue" peut être après chaque 'voiture' ou boucle ...

par exemple:

>>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [x for y in z if sum(y)>10 for x in y if x < 10]
[5, 6, 7, 8, 9]

En boucle for régulière:

>>> for y in z:
    if sum(y)>10:
        for x in y:
            if x < 10:
                print x

5
6
7
8
9
92
Inbar Rose

De la liste de documentation de compréhension :

Lorsqu'une compréhension de liste est fournie, elle se compose d'une seule expression suivie d'au moins une clause for et de zéro ou plusieurs clauses for ou if. Dans ce cas, les éléments de la nouvelle liste sont ceux qui seraient produits en considérant chacune des clauses for ou if comme un bloc, imbriquées de gauche à droite et en évaluant l'expression pour produire un élément de liste chaque fois que le bloc le plus intérieur est atteint .

En d'autres termes, faites comme si les boucles for sont imbriquées. La lecture de gauche à droite de votre compréhension de liste peut être imbriquée comme:

for elem in vec:
    for num in elem:
        num           # the *single expression* from the spec

où la compréhension de la liste utilisera ce dernier bloc le plus à l'intérieur comme valeurs de la liste résultante.

8
Martijn Pieters

Votre code est égal à:

temp = []
for elem in vec:
    for num in elem:
        temp.append(num)
6
zhangyangyu