Einzeilig verschachtelt für Schleifen

102

Schrieb diese Funktion in Python, das eine Matrix transponiert:

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

Dabei wurde mir klar, dass ich nicht vollständig verstehe, wie einzelne für Schleifen verschachtelte Zeilen ausgeführt werden. Bitte helfen Sie mir beim Verständnis, indem Sie die folgenden Fragen beantworten:

  1. In welcher Reihenfolge wird diese for-Schleife ausgeführt?
  2. Wenn ich eine dreifach verschachtelte for-Schleife hätte, welche Reihenfolge würde sie ausführen?
  3. Was wäre gleich die gleiche nicht verschachtelte for-Schleife?

Gegeben,

[ function(i,j) for i,j in object ]
  1. Welcher Typ muss ein Objekt sein, um dieses für die Schleifenstruktur zu verwenden?
  2. In welcher Reihenfolge werden i und j Elementen im Objekt zugewiesen?
  3. Kann es durch eine andere for-Schleifenstruktur simuliert werden?
  4. Kann diese for-Schleife mit einer ähnlichen oder anderen Struktur für die Schleife verschachtelt werden? Und wie würde es aussehen?

Zusätzliche Informationen sind ebenfalls willkommen.

Asher Girlande
quelle

Antworten:

169

Die beste Informationsquelle ist das offizielle Python-Tutorial zum Listenverständnis . Das Listenverständnis ist fast das gleiche wie für Schleifen (sicherlich kann jedes Listenverständnis als for-Schleife geschrieben werden), aber sie sind oft schneller als die Verwendung einer for-Schleife.

Schauen Sie sich dieses längere Listenverständnis aus dem Tutorial an (der ifTeil filtert das Verständnis, nur Teile, die die if-Anweisung bestehen, werden an den letzten Teil des Listenverständnisses übergeben (hier (x,y)):

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Es ist genau das gleiche wie diese verschachtelte for-Schleife (und wie im Tutorial angegeben, beachten Sie, wie die Reihenfolge von for und if identisch ist).

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Der wesentliche Unterschied zwischen einer Liste Verständnis und einem for - Schleife ist , dass der letzte Teil der for - Schleife (wo man etwas tun) kommt am Anfang und nicht am Ende.

Weiter zu Ihren Fragen:

Welcher Typ muss ein Objekt sein, um dieses für die Schleifenstruktur zu verwenden?

Eine iterable . Jedes Objekt, das eine (endliche) Menge von Elementen erzeugen kann. Dazu gehören alle Container, Listen, Mengen, Generatoren usw.

In welcher Reihenfolge werden i und j Elementen im Objekt zugewiesen?

Sie werden in genau derselben Reihenfolge zugewiesen, in der sie aus jeder Liste generiert wurden, als wären sie in einer verschachtelten for-Schleife (für Ihr erstes Verständnis würden Sie 1 Element für i erhalten, dann jeden Wert von j, 2. Element in i, dann jeder Wert von j usw.)

Kann es durch eine andere for-Schleifenstruktur simuliert werden?

Ja, bereits oben gezeigt.

Kann diese for-Schleife mit einer ähnlichen oder anderen Struktur für die Schleife verschachtelt werden? Und wie würde es aussehen?

Sicher, aber es ist keine gute Idee. Hier finden Sie beispielsweise eine Liste mit Zeichenlisten:

[[ch for ch in word] for word in ("apple", "banana", "pear", "the", "hello")]
Jeff Tratner
quelle
Ich frage mich, was ihre Wahl der Bestellung in der Doppelverschachtelung geleitet hat. Ich finde den anderen Weg natürlicher (für y als für x in Ihrem Beispiel). Mir ist nur klar, dass ich nach 3 Jahren Python (nicht ausgiebig, aber immer noch ...) und solchen Loops verwendet habe !!
Thomas
@Thomas finde ich auch umgekehrt intuitiver. Die Wahl, die ich glaube, war reine Bequemlichkeit. Eine intuitivere Vorgehensweise würde bedeuten, dass Sie sich mit ungelösten Symbolen befassen müssen, bis sie später in der Anweisung gefunden werden. Versuchen Sie, für jede banana.peel in jeder Banane für jede city.bananastore in jeder Stadt auf Papier zu analysieren. Nicht so einfach. Umgekehrt schön und einfach.
Pyjong
29

Das könnte Sie interessieren itertools.product, das ein iterables Ergebnis liefert, das Tupel von Werten aus allen iterierbaren Werten ergibt, die Sie übergeben. Das heißt, es werden itertools.product(A, B)alle Werte der Form ausgegeben (a, b), von denen die aWerte stammen Aund von denen die bWerte stammen B. Beispielsweise:

import itertools

A = [50, 60, 70]
B = [0.1, 0.2, 0.3, 0.4]

print [a + b for a, b in itertools.product(A, B)]

Dies druckt:

[50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]

Beachten Sie, dass das letzte übergebene Argument itertools.productdas "innere" ist. Im Allgemeinen ist gleichitertools.product(a0, a1, ... an)[(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]

Lynn
quelle
4

Zunächst verwendet Ihr erster Code keine for-Schleife an sich, sondern ein Listenverständnis .

  1. Wäre gleichbedeutend mit

    für j im Bereich (0, Breite): für i im Bereich (0, Höhe): m [i] [j]

  2. Ähnlich nistet es im Allgemeinen wie bei Schleifen von rechts nach links. Die Syntax des Listenverständnisses ist jedoch komplexer.

  3. Ich bin mir nicht sicher, was diese Frage stellt


  1. Jedes iterierbare Objekt, das iterierbare Objekte liefert, die genau zwei Objekte ergeben (was für ein Schluck - dh [(1,2),'ab']gültig wäre)

  2. Die Reihenfolge, in der das Objekt bei der Iteration nachgibt. igeht zur ersten Ausbeute, jzur zweiten.

  3. Ja, aber nicht so hübsch. Ich glaube, es ist funktional gleichbedeutend mit:

    l = list ()
    für i, j im Objekt:
        l.append (Funktion (i, j))
    

    oder noch besser Karte verwenden :

    map(function, object)

    Aber natürlich würde Funktion erhalten i, jselbst.

  4. Ist das nicht die gleiche Frage wie 3?

korylprince
quelle
2

Mit der zipFunktion können Sie zwei for-Schleifen in derselben Zeile verwenden

Code:

list1 = ['Abbas', 'Ali', 'Usman']
list2 = ['Kamran', 'Asgar', 'Hamza', 'Umer']
list3 = []
for i,j in zip(list1,list2):
    list3.append(i)
    list3.append(j)
print(list3)

Ausgabe:

['Abbas', 'Kamran', 'Ali', 'Asgar', 'Usman', 'Hamza']

Mit der Zip-Funktion können wir also zwei for-Schleifen verwenden oder zwei Listen in derselben Zeile iterieren.

Muhammad Abbas
quelle
-1

Der folgende Code enthält die besten Beispiele für verschachtelte Schleifen. Wenn Sie zwei for-Schleifen verwenden, denken Sie bitte daran, dass die Ausgabe der ersten Schleife für die zweite Schleife eingegeben wird. Schleifenbeendigung auch wichtig bei Verwendung der verschachtelten Schleifen

for x in range(1, 10, 1):
     for y in range(1,x):
             print y,
        print
OutPut :
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
Rameshbabu Reddy
quelle