Zugriff auf den Index in 'Foreach'-Schleifen in Python

Wenn Sie in Python über eine Sammlung von Elementen in einer Schleife laufen, müssen Sie oft auch eine Ordinalzahl mit jedem Element verknüpfen. Eine solche Zahl wird üblicherweise als Index bezeichnet.

Der pythonische Weg, auf den Index zuzugreifen, während Sie eine foreach-Schleife ausführen, ist die Verwendung der eingebauten Funktion enumerate().

enumerate() fügt einen Index zu jedem Element einer iterierbaren Sammlung hinzu. Sie können dann die eingebaute Funktion list() benutzen, um eine Liste von Tupeln zurückzubekommen.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names))
[(0, 'Bob'), (1, 'Alice'), (2, 'John'), (3, 'Cindy')]

Beachten Sie, dass die Indizierung in Python bei 0 beginnt.

Wenn Sie jedoch die Indizierung von 1 aus starten wollen (z.B. wenn Sie einen Bericht ausdrucken), ist es trivial, wenn Sie ein zusätzliches start Argument an enumerate übergeben.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> list(enumerate(names), start=1)
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]

Der obige Ansatz ist auch nützlich, wenn Sie Daten aus verschiedenen Datenquellen drucken, aber einen konsistenten Index über alle Datenelemente hinweg haben wollen.

>>> data_source1 = ['Bob', 'Alice', 'John', 'Cindy']
>>> data_source2 = ['Sarah', 'Jeff', 'Emily', 'Adam']
>>> list(enumerate(data_source1, start=1))
[(1, 'Bob'), (2, 'Alice'), (3, 'John'), (4, 'Cindy')]
>>> list(enumerate(data_source2, start=len(data_source1) + 1))
[(5, 'Sarah'), (6, 'Jeff'), (7, 'Emily'), (8, 'Adam')]

Beachten Sie, dass Sie ein Enumerate Objekt nicht in eine Liste konvertieren müssen. Es ist selbst ein iterierbares Objekt, so dass Sie direkt darüber iterieren können.

>>> names = ['Bob', 'Alice', 'John', 'Cindy']
>>> for idx, name in enumerate(names):
...   print(name)
...
Bob
Alice
John
Cindy

Es kann andere Wege geben, den Index während der Iteration über eine Sammlung von Objekten zu erhalten, aber die Verwendung von enumerate() wird als kanonisch angesehen und wird bevorzugt.

Eine andere Möglichkeit wäre es, eine separate Index-Variable zu verwenden, diese manuell zu initialisieren und bei jeder Iteration manuell inkrementieren. Ein solcher Ansatz würde jedoch als eine Neuerfindung des Rades angesehen und verpönt sein.

Hier ist ein Zitat aus PEP 279, in dem die Funktion enumerate() eingeführt wurde.

Dieser PEP führt eine neue eingebaute Funktion ein, enumerate(), um eine häufig verwendete Schleifensprache zu vereinfachen. Sie bietet allen iterierbaren Sammlungen den gleichen Vorteil, den iteritems() für Wörterbücher bietet – eine kompakte, lesbare, zuverlässige Indexnotation.

Sie können fragen, ob es irgendwelche Performance-Implikationen bei der Verwendung von enumerate in Ihrem Code gibt. Nun, es steht Ihnen frei, alle Messungen vorzunehmen, aber bitte bedenken Sie, dass enumerate ein idiomatischer Weg ist, um auf den Index einer Iterationsschleife in einer for-each-Schleife zuzugreifen. Idiomatischer Code wird von den Python-Maintainern empfohlen und sie werden alles zu damit es effizient läuft.

Und für diejenigen von Ihnen, die unten am neugierigsten sind, ist eine mögliche Implementierung der enumerate() Funktion aus dem obigen PEP.

def enumerate(collection):
   'Generates an indexed series:  (0,coll[0]), (1,coll[1]) ...'
   i = 0
   it = iter(collection)
   while 1:
       yield (i, it.next())
       i += 1
comments powered by Disqus