2013-07-15 5 views
31
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] 

To mnie wykańcza.
Rozumiem, że elem to lista wewnątrz listy z for elem in vic
Nie do końca rozumiem użycie num i for num in elem na początku i na końcu.Zrozumienie listy Pythona podwójne dla

W jaki sposób Python to interpretuje?
Jaka jest kolejność, na którą wygląda?

+0

możliwe duplikat [Podwójne iteracji listowego] (http://stackoverflow.com/questions/1198777/double -iteracja-w-spisie-pojmowanie) –

+3

To nie jest wielki cel dupaku, @Inbar, ponieważ nie wyjaśnia nic o tym, jak Python interpretuje kolejność zagnieżdżonych pętli. –

+0

Powiązane/możliwe dupe: [zagnieżdżone wyliczenia list] (http://stackoverflow.com/a/11934483) –

Odpowiedz

60

Zróbmy to.

Prosty list-zrozumieniem:

[x for x in collection] 

Łatwo to zrozumieć, jeśli łamiemy go na części: [A for B in C]

  • A jest elementem, który będzie w otrzymanym liście
  • B to każdy element w kolekcji C
  • C jest samą kolekcją.

W ten sposób, można napisać:

[x.lower() for x in words] 

W celu przekształcenia wszystkie słowa w liście na małe litery.


Jest komplikować, kiedy to z innej listy tak:

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

Tutaj coś specjalnego się nie dzieje. Chcemy, aby nasza ostateczna lista zawierała pozycje A, a pozycje A znajdowały się w elementach B, więc musimy powiedzieć o tym zrozumieniu listy.

  • A jest elementem, który będzie w otrzymanym liście
  • B jest każdy element w kolekcji C
  • C jest kolekcja sama
  • D jest każdy element w kolekcji E (w tym obudowa, także A)
  • E to kolejna kolekcja (w tym przypadku)

Logika ta jest podobna do normalnej pętli for:

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 

Aby rozwinąć na ten temat, i dają świetny przykład + wyjaśnienie, wyobrazić sobie, że jest pociąg.

Silnik pociągu (przednia) jest zawsze będzie tam (wynik list-zrozumieniem)

Następnie istnieją dowolną liczbę wagonów, każdy wagon ma postać: for x in y

lista rozumienie mógłby wyglądać następująco:

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

które byłoby jakby regularny dla pętli:

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

Innymi słowy, zamiast iść w dół do linii i wcięcia, w zrozumieniu listy wystarczy dodać kolejną pętlę do końca.

Aby powrócić do analogii kolejowego:

Engine - Car - Car - Car ... Tail

Co jest ogon? Ogon jest specjalną rzeczą na listach. Nie trzeba jeden, ale jeśli masz ogon, ogon jest stanem, spojrzeć na ten przykład:

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

To daje każdy wiersz w pliku, dopóki linia nie zrobił” t zaczyna się od hashtagu (#), inne są po prostu pomijane.

Sztuczka polegająca na użyciu "ogona" pociągu polega na tym, że jest sprawdzana pod kątem Prawda/Fałsz w tym samym czasie, w którym masz ostatni "Silnik" lub "wynik" ze wszystkich pętli, powyższy przykład w regularne dla pętli będzie wyglądać następująco:

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

uwaga: choć w mojej analogii pociągu jest tylko „ogon” na końcu pociągu, warunek lub „ogon” może być po co "samochód" lub pętli ...

na przykład:

>>> 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] 

w zwykłych dla pętli:

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

5 
6 
7 
8 
9 
+0

Twoja odpowiedź oznacza, że ​​możesz użyć tylko instrukcji "if" na końcu listy. To nie jest prawda. Możesz użyć instrukcji if na poziomie * any * w swoich listach, a nawet umieścić kilka po sobie (choć to wygląda trochę bezsensownie, dopóki nie zorientujesz się, że są zagnieżdżone). Po prostu nie możesz użyć 'if' jako * pierwszego * elementu, który musi być pętlą' for'. –

+2

Masz rację, nie chciałem sugerować, że ja to wyjaśnię. –

+0

Muszę powiedzieć, że twoje wyjaśnienie ogromnie nadmiernie komplikuje rzeczy. Zwłaszcza, gdy zaczniesz rozszerzać 'A dla B w C dla D w E' na zagnieżdżoną pętlę z' dla B w C: 'i' dla A w B', odrzucając część 'dla D w E'. –

6

Kod wynosi:

temp = [] 
for elem in vec: 
    for num in elem: 
     temp.append(num) 
+4

Zwróć uwagę, że instrukcje 'for' są zapisane w zrozumieniu listy w tej samej kolejności, w jakiej zostałyby napisane, gdybyś tylko zrobił napisałem regularne pętle 'for' jak wyżej. – kindall

7

Od list comprehension documentation:

Gdy lista rozumienie jest dostarczany, składa się z jednego wyrazu, po czym przynajmniej jeden for klauzuli i zero lub więcej for lub klauzule if. W tym przypadku elementy nowej listy są tymi, które zostałyby utworzone poprzez uznanie każdej z klauzul for lub if za zagnieżdżone od lewej do prawej strony i ocenę wyrażenia w celu utworzenia elementu listy za każdym razem, gdy zostanie osiągnięty najgłębszy blok .

Innymi słowy, udawaj, że pętle for są zagnieżdżone. Czytając od lewej do prawej swoją listowych można zagnieżdżać jak:

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

gdzie lista zrozumienie użyje tego ostatniego, jak najgłębsze blok wartości otrzymanej listy.