PEP 279 – Die eingebaute Funktion enumerate()
- Autor:
- Raymond Hettinger <python at rcn.com>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 30. Jan 2002
- Python-Version:
- 2.3
- Post-History:
Zusammenfassung
Dieses PEP führt eine neue eingebaute Funktion, enumerate(), ein, um ein häufig verwendetes Schleifenidiom zu vereinfachen. Sie bietet allen iterierbaren Sammlungen den gleichen Vorteil, den iteritems() Wörterbüchern bietet – eine kompakte, lesbare und zuverlässige Indexnotation.
Begründung
Python 2.2 führte das Konzept einer iterierbaren Schnittstelle ein, wie in PEP 234 vorgeschlagen. Die iter() Factory-Funktion wurde als gängige Aufrufkonvention bereitgestellt und tiefgreifende Änderungen wurden vorgenommen, um Iteratoren als ein einheitliches Thema in ganz Python zu verwenden. Die Vereinheitlichung erfolgte in Form der Etablierung einer gemeinsamen iterierbaren Schnittstelle für Mappings, Sequenzen und Datei-Objekte.
Generatoren, wie in PEP 255 vorgeschlagen, wurden als Mittel eingeführt, um die Erstellung von Iteratoren zu erleichtern, insbesondere solchen mit komplexer interner Ausführung oder variablen Zuständen. Die Verfügbarkeit von Generatoren macht es möglich, die Ideen für Schleifenzähler aus PEP 212 zu verbessern. Diese Ideen boten eine saubere Syntax für die Iteration mit Indizes und Werten, waren aber nicht auf alle iterierbaren Objekte anwendbar. Außerdem hatte dieser Ansatz nicht den speicherschonenden Vorteil, der durch Generatoren geboten wird, die nicht die gesamte Sequenz auf einmal auswerten.
Der neue Vorschlag ist die Hinzufügung einer eingebauten Funktion, enumerate(), die durch die Verfügbarkeit von Iteratoren und Generatoren ermöglicht wurde. Sie bietet allen iterierbaren Objekten den gleichen Vorteil, den iteritems() Wörterbüchern bietet – eine kompakte, lesbare und zuverlässige Indexnotation. Ähnlich wie zip() wird erwartet, dass sie zu einem häufig verwendeten Schleifenidiom wird.
Dieser Vorschlag wurde entwickelt, um die bestehende Implementierung zu nutzen und erfordert nur geringen zusätzlichen Aufwand zur Integration. Er ist abwärtskompatibel und benötigt keine neuen Schlüsselwörter. Der Vorschlag wird in Python 2.3 aufgenommen, wenn Generatoren final sind und nicht mehr aus __future__ importiert werden.
BDFL-Bekanntmachungen
Die neue eingebaute Funktion wird AKZEPTIERT.
Spezifikation für eine neue eingebaute Funktion
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
Hinweis A: PEP 212 Loop Counter Iteration diskutierte mehrere Vorschläge zur Erreichung von Indizierung. Einige der Vorschläge funktionieren nur für Listen, im Gegensatz zur obigen Funktion, die für jeden Generator, xrange, jede Sequenz oder jedes iterierbare Objekt funktioniert. Außerdem wurden diese Vorschläge in der Zeit vor Python 2.2 präsentiert und bewertet, die keine Generatoren enthielt. Infolgedessen hatte die Nicht-Generator-Version in PEP 212 den Nachteil, dass sie Speicher mit einer riesigen Liste von Tupeln verbrauchte. Die hier präsentierte Generator-Version ist schnell und leicht, funktioniert mit allen iterierbaren Objekten und ermöglicht es Benutzern, die Sequenz mitten im Strom abzubrechen, ohne dass Rechenaufwand verloren geht.
Es gibt andere PEPs, die sich mit verwandten Themen befassen: Integer-Iteratoren, Integer-for-Schleifen und eine zur Änderung der Argumente von range und xrange. Der enumerate() Vorschlag schließt die anderen Vorschläge nicht aus und erfüllt weiterhin ein wichtiges Bedürfnis, auch wenn diese übernommen werden – das Bedürfnis, Elemente in jedem iterierbaren Objekt zu zählen. Die anderen Vorschläge bieten ein Mittel zur Erzeugung eines Index, aber nicht des entsprechenden Wertes. Dies ist besonders problematisch, wenn eine Sequenz gegeben wird, die keinen direkten Zugriff unterstützt, wie z. B. ein Datei-Objekt, ein Generator oder eine mit __getitem__ definierte Sequenz.
Hinweis B: Fast alle PEP-Gutachter begrüßten die Funktion, waren sich aber uneinig darüber, ob es überhaupt eingebaute Funktionen geben sollte. Das Hauptargument für ein separates Modul war die Verlangsamung der Sprachinflation. Das Hauptargument für eine eingebaute Funktion war, dass die Funktion dazu bestimmt ist, Teil eines Kernprogrammierstils zu sein, der für jedes Objekt mit einer iterierbaren Schnittstelle gilt. So wie zip() das Problem des Schleifens über mehrere Sequenzen löst, löst die enumerate() Funktion das Problem des Schleifenzählers.
Wenn nur eine eingebaute Funktion erlaubt ist, dann ist enumerate() das wichtigste allgemeine Werkzeug, das die breiteste Klasse von Problemen löst und gleichzeitig die Kürze, Klarheit und Zuverlässigkeit von Programmen verbessert.
Hinweis C: Verschiedene alternative Namen wurden diskutiert
iterindexed() |
fünf Silben sind eine Mundvoll |
index() |
schönes Verb, könnte aber mit der .index() Methode verwechselt werden |
indexed() |
weitgehend beliebt, aber Adjektive sollten vermieden werden |
indexer() |
Substantiv las sich in einer for-Schleife nicht gut |
count() |
direkt und explizit, wird aber oft in anderen Kontexten verwendet |
itercount() |
direkt, explizit und von mehr als einer Person gehasst |
iteritems() |
konfligiert mit dem Schlüssel:Wert-Konzept für Wörterbücher |
itemize() |
verwirrend, da amap.items() != list(itemize(amap)) |
enum() |
prägnant; weniger klar als enumerate; zu ähnlich zu enum in anderen Sprachen, wo es eine andere Bedeutung hat |
Alle Namen, die "count" enthielten, hatten den weiteren Nachteil, dass sie implizierten, dass der Zähler bei eins und nicht bei null beginnt.
Alle Namen, die "index" enthielten, kollidierten mit der Verwendung in Datenbanksprachen, wo Indizierung eine Sortieroperation und keine lineare Sequenzierung impliziert.
Hinweis D: Diese Funktion wurde ursprünglich mit optionalen Start- und Stoppargumenten vorgeschlagen. GvR wies darauf hin, dass der Funktionsaufruf enumerate(seqn,4,6) eine alternative, plausible Interpretation als Slice hatte, die das vierte und fünfte Element der Sequenz zurückgeben würde. Um die Mehrdeutigkeit zu vermeiden, wurden die optionalen Argumente gestrichen, auch wenn dies den Verlust an Flexibilität als Schleifenzähler bedeutete. Diese Flexibilität war am wichtigsten für den häufigen Fall des Zählens ab eins, wie in
for linenum, line in enumerate(source,1): print linenum, line
- Kommentare von GvR
filterundmapsollten sterben und in Listenkomprehensionen aufgehen, nicht mehr Varianten hervorbringen. Ich würde eher eingebaute Funktionen einführen, die Iterator-Algebra betreiben (z. B. das Iterzip, das ich oft als Beispiel verwendet habe).Ich mag die Idee, eine Möglichkeit zu haben, über eine Sequenz und ihre Indexmenge parallel zu iterieren. Es ist in Ordnung, wenn dies eine eingebaute Funktion ist.
Ich mag den Namen "indexed" nicht; Adjektive sind keine guten Funktionsnamen. Vielleicht
iterindexed()?- Kommentare von Ka-Ping Yee
- Ich bin auch ziemlich zufrieden mit allem, was Sie vorgeschlagen haben ... und die zusätzlichen eingebauten Funktionen (wirklich 'indexed' im Besonderen) sind Dinge, die ich schon lange gewollt habe.
- Kommentare von Neil Schemenauer
- Die neuen eingebauten Funktionen klingen in Ordnung. Guido mag Bedenken haben, die Anzahl der eingebauten Funktionen zu stark zu erhöhen. Es wäre vielleicht besser, sie als Teil eines Moduls zu verkaufen. Wenn Sie ein Modul verwenden, können Sie viele nützliche Funktionen hinzufügen (Haskell hat viele davon, die wir stehlen könnten).
- Kommentare für Magnus Lie Hetland
- Ich denke, 'indexed' wäre eine nützliche und natürliche eingebaute Funktion. Ich würde sie sicherlich oft verwenden. Ich mag
indexed()sehr; +1. Ich bin ziemlich froh, dass sie PEP 281 obsolet macht. Das Hinzufügen eines separaten Moduls für Iterator-Dienstprogramme scheint eine gute Idee zu sein. - Kommentare aus der Community
- Die Resonanz auf den
enumerate()Vorschlag war fast zu 100 % positiv. Fast jeder liebt die Idee. - Antwort des Autors
- Vor diesen Kommentaren wurden vier eingebaute Funktionen vorgeschlagen. Nach den Kommentaren wurden
xmap,xfilterundxzipzurückgezogen. Die verbleibende ist für die Sprache von entscheidender Bedeutung und wird allein vorgeschlagen.Indexed()ist trivial einfach zu implementieren und kann in wenigen Minuten dokumentiert werden. Wichtiger ist, dass sie in der alltäglichen Programmierung nützlich ist, die sonst keine explizite Verwendung von Generatoren beinhaltet.Dieser Vorschlag enthielt ursprünglich eine weitere Funktion
iterzip(). Diese wurde anschließend alsizip()Funktion imitertoolsModul implementiert.
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0279.rst
Zuletzt geändert: 2025-02-01 08:55:40 GMT