Wie ermittle ich in Python, ob ein Objekt iterierbar ist?
Gibt es eine Methode wie isiterable
? Die einzige Lösung, die ich bis jetzt gefunden habe ist der Aufruf
hasattr(myObj, '__iter__')
Aber ich bin nicht sicher, wie narrensicher diese ist.
InformationsquelleAutor der Frage willem | 2009-12-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Prüfung für
__iter__
arbeitet in Sequenz-Typen, aber es würde fehlschlagen, z.B. strings in Python 2. Ich würde gerne wissen, die richtige Antwort zu haben, bis dann, hier ist eine Möglichkeit (das würde die Arbeit auf den Saiten, zu):Den
iter
eingebauten Kontrollen für die__iter__
Methode oder im Fall von strings, die__getitem__
Methode.Anderen Allgemeinen pythonic Ansatz davon aus, dass ein iterierbar dann ordnungsgemäß fehl, wenn Sie nicht arbeiten auf dem gegebenen Objekt. Die Python-Glossar:
Den
Sammlungen
Modul stellt eine abstrakte Basis-Klassen, die es erlauben, zu Fragen, - Klassen oder-Instanzen, wenn Sie bieten bestimmte Funktionen, zum Beispiel:Allerdings bedeutet dies nicht, überprüfen Sie für Klassen, die sind iterierbar durch
__getitem__
.InformationsquelleAutor der Antwort miku
Duck typing
Typ-überprüfung
Verwenden Sie die Abstrakte Basisklassen. Sie müssen mindestens Python 2.6 und arbeiten nur für new-style-Klassen.
Jedoch
iter()
ist ein bisschen mehr zuverlässig, wie beschrieben durch die Dokumentation:InformationsquelleAutor der Antwort Georg Schölly
Möchte ich Schuppen ein wenig mehr Licht auf das zusammenspiel von
iter
__iter__
und__getitem__
und was passiert hinter den kulissen. Bewaffnet mit diesem wissen, werden Sie in der Lage zu verstehen, warum die besten, die Sie tun können, istWerde ich eine Liste der Fakten, die erste und Folgen Sie dann mit einem schnellen Erinnerung daran, was passiert, wenn Sie verwenden einen
for
- Schleife in python, gefolgt von einer Diskussion zur Veranschaulichung der Fakten.Fakten
Können Sie sich einen iterator von einem Objekt
o
durch den Aufrufiter(o)
wenn mindestens eine der folgenden Bedingungen gilt:a)
o
hat eine__iter__
Methode liefert ein iterator-Objekt. Ein iterator ist ein Objekt ein__iter__
und ein__next__
(Python 2:next
) - Methode.b)
o
hat eine__getitem__
Methode.Überprüfung auf eine Instanz von
Iterable
oderSequence
oder überprüfung der für dieAttribut
__iter__
ist nicht genug.Wenn ein Objekt
o
implementiert nur__getitem__
aber nicht__iter__
iter(o)
konstruierenein iterator, der versucht zu Holen die Elemente aus
o
integer index, starting at index 0. Der iterator wird fangen alleIndexError
(aber keine anderen Fehler), der ausgelöst wird, und dann wirftStopIteration
selbst.In den meisten Allgemeinen Sinn, es gibt keinen Weg, um zu überprüfen, ob der iterator zurückgegeben
iter
ist vernünftiger, als es auszuprobieren.Wenn ein Objekt
o
implementiert__iter__
dieiter
Funktion stellen Sie sicher,dass das Objekt zurückgegeben
__iter__
ist ein iterator. Es gibt keine Plausibilitätsprüfungwenn ein Objekt implementiert nur
__getitem__
.__iter__
gewinnt. Wenn ein Objekto
implementiert sowohl__iter__
und__getitem__
iter(o)
rufen__iter__
.Wenn Sie möchten, um Ihre eigenen Objekte wiederholenden, immer umsetzen die
__iter__
Methode.for
SchleifenUm zu Folgen, benötigen Sie ein Verständnis von dem, was passiert, wenn Sie verwenden einen
for
- Schleife in Python. Fühlen Sie sich frei, zu überspringen und direkt zum nächsten Abschnitt, wenn Sie schon wissen.Wenn Sie
for item in o
für einige wiederholenden Objekto
-, Python-Aufrufeiter(o)
und erwartet, dass ein iterator-Objekt als Rückgabewert. Ein iterator ist ein Objekt, das implementiert eine__next__
(odernext
in Python 2) - Methode und eine__iter__
Methode.Durch Konvention, die
__iter__
Methode einen iterator zurückgeben sollte, das Objekt selbst (d.h.return self
). Python ruft dannnext
auf den iterator bisStopIteration
ausgelöst. All dies geschieht implizit, aber das folgende Beispiel macht es sichtbar:Iteration über eine
DemoIterable
:Diskussion und Illustrationen
Auf Punkt 1 und 2: immer ein iterator und unzuverlässig überprüft
Betrachten Sie die folgende Klasse:
Aufrufen
iter
mit einer Instanz vonBasicIterable
zurück einen iterator ohne Probleme, weilBasicIterable
implementiert__getitem__
.Es ist jedoch wichtig zu beachten, dass
b
nicht die__iter__
Attribut und nicht als eine Instanz vonIterable
oderSequence
:Dies ist der Grund, warum Fließend Python von Luciano Ramalho empfiehlt Berufung
iter
- und Umgang mit dem PotenzialTypeError
als der Genaueste Weg, um zu überprüfen, ob ein Objekt ist iterierbar. Zitiert direkt aus dem Buch:Punkt 3: Iteration über Objekte, die nur zur
__getitem__
aber nicht__iter__
Iteration über eine Instanz von
BasicIterable
funktioniert wie erwartet: PythonKonstrukte, die einen iterator, der versucht zu Holen Elemente, die durch den index, beginnend bei null, bis eine
IndexError
ausgelöst. Die demo-Objekt__getitem__
Methode gibt einfach dieitem
was geliefert wurde als argument für__getitem__(self, item)
durch den iterator zurückgegebeniter
.Beachten Sie, dass der iterator wirft
StopIteration
wenn es nicht zurück, das nächste Element und dieIndexError
die ausgelöst wird, füritem == 3
intern. Dies ist der Grund, warum looping über eineBasicIterable
mit einemfor
- Schleife funktioniert wie erwartet:Hier ist ein weiteres Beispiel, um nach Hause zu fahren, das Konzept, wie der iterator zurückgegeben
iter
versucht, Zugriff auf Elemente über index.WrappedDict
erbt nicht vondict
was bedeutet, dass Instanzen nicht ein__iter__
Methode.Beachten Sie, dass Anrufe zu
__getitem__
übertragen sinddict.__getitem__
für die die eckige Klammer notation ist einfach ein Kürzel.Auf Punkt 4 und 5:
iter
Prüfungen für ein iterator, wenn er fordert__iter__
:Wenn
iter(o)
genannt wird, für ein Objekto
iter
wird, stellen Sie sicher, dass der Rückgabewert von__iter__
wenn die Methode vorhanden ist, ist ein iterator. Dies bedeutet, dass das zurückgegebene Objektumsetzen muss
__next__
(odernext
in Python 2) und__iter__
.iter
nicht durchführen jegliche Vernunft überprüft, für Objekte, die nurbieten
__getitem__
, da es keine Möglichkeit hat zu überprüfen, ob die Elemente des Objekts zugänglich sind integer-index.Beachten Sie, dass die Konstruktion eines iterator von
FailIterIterable
Instanzen nicht sofort, bei der Konstruktion einen iterator vonFailGetItemIterable
erfolgreich, aber es wird eine Ausnahme ausgelöst, die auf den ersten Aufruf__next__
.Auf Punkt 6:
__iter__
gewinntDieser ist einfach. Wenn ein Objekt implementiert
__iter__
und__getitem__
iter
rufen__iter__
. Betrachten Sie die folgende Klasseund die Ausgabe beim Durchlaufen einer Instanz:
Auf Punkt 7: Ihre iterierbar Klassen implementieren sollte
__iter__
Fragen Sie sich vielleicht, warum die meisten builtin-Sequenzen wie
list
Umsetzung einer__iter__
Methode, wenn__getitem__
ausreichen würde.Nachdem alle, iteration über Instanzen der Klasse vor, die Delegierten Aufrufe
__getitem__
zulist.__getitem__
(Verwendung von eckigen Klammern-notation), funktioniert Prima:Den Gründen Ihrer benutzerdefinierten iterables umsetzen sollte
__iter__
sind wie folgt:__iter__
Instanzen werden als iterables undisinstance(o, collections.Iterable)
zurückTrue
.__iter__
ist nicht ein iteratoriter
wird sofort fehl und heben einenTypeError
.__getitem__
vorhanden, um die Abwärtskompatibilität zu Gründen. Zitieren wieder aus Fließend Python:InformationsquelleAutor der Antwort timgeb
Dies ist nicht ausreichend: das Objekt zurückgegeben
__iter__
implementieren muss, um die iteration Protokoll (d.h.next
- Methode). Siehe den entsprechenden Abschnitt in der Dokumentation.In Python, eine gute übung ist, zu versuchen und sehen" statt "prüfen".
InformationsquelleAutor der Antwort jldupont
Nicht ausführen, überprüft, um zu sehen,
wenn Ihre Ente ist wirklich eine Enteum zu sehen, ob es durchsuchbar ist oder nicht, behandeln Sie, als ob es war und sich beschweren, wenn er es nicht war.InformationsquelleAutor der Antwort badp
Die beste Lösung, die ich bisher gefunden habe:
hasattr(obj, '__contains__')
was im Grunde überprüft, ob das Objekt implementiert die
in
Betreiber.Vorteile (keine der anderen Lösungen hat alle drei):
__iter__
)Hinweise:
InformationsquelleAutor der Antwort Vlad
In Python <= 2.5, Sie kann und darf nicht - wiederholenden war eine "informelle" - Schnittstelle.
Aber seit Python 2.6 und 3.0 nutzen Sie das neue ABC (abstract base class) - Infrastruktur zusammen mit einigen builtin-ABC, die verfügbar sind in den Sammlungen Modul:
Nun, ob dies wünschenswert ist oder tatsächlich funktioniert, ist nur eine Frage der Konventionen. Wie Sie sehen können, Sie kann registrieren Sie einen nicht-wiederholenden Objekt als Iterierbar - und es wirft eine exception zur Laufzeit. Daher isinstance erwirbt eine "neue" Bedeutung - es prüft nur für "erklärt" haben, geben Sie Kompatibilität, das ist ein guter Weg zu gehen, um in Python.
Auf der anderen Seite, wenn Ihr Objekt nicht erfüllt, die der Schnittstelle, die Sie brauchen, was werden Sie tun? Nehmen Sie das folgende Beispiel:
Wenn das Objekt nicht zufrieden sind, was Sie erwarten, werden Sie nur werfen eine TypeError, aber wenn die richtigen ABC registriert wurde, überprüfen Sie Ihre unuseful. Im Gegenteil, wenn die
__iter__
Methode verfügbar ist Python erkennt automatisch Objekt der Klasse als Durchsuchbar.So, wenn Sie nur erwarten, dass ein iterierbar, Durchlaufen Sie es und vergessen Sie es. Auf der anderen Seite, wenn Sie benötigen, um verschiedene Dinge tun, je nach Eingabe-Typ, finden Sie vielleicht die ABC-Infrastruktur ziemlich nützlich.
InformationsquelleAutor der Antwort Alan Franzoni
Fand ich eine schöne Lösung hier:
InformationsquelleAutor der Antwort jbochi
Könnten Sie versuchen, diese:
Wenn wir einen generator, durchläuft es (aber verwenden Sie niemals den generator, so dass es nicht nehmen Platz), es ist durchsuchbar. Scheint wie ein "duh" Art der Sache. Warum brauchen Sie, um festzustellen, ob eine variable ist durchsuchbar?
InformationsquelleAutor der Antwort Chris Lutz
Entsprechend der Python-2 Glossariterables sind
Natürlich, angesichts der Allgemeinen coding-style für Python basiert auf der Tatsache, dass es "Einfacher um Vergebung zu bitten als Erlaubnis.", die Allgemeine Erwartung ist die Verwendung
Aber wenn Sie brauchen, um zu überprüfen es sich ausdrücklich vor, die Sie testen können, für eine iterierbar von
hasattr(object_in_question, "__iter__") or hasattr(object_in_question, "__getitem__")
. Sie müssen prüfen, für beide, weilstr
s nicht__iter__
Methode (zumindest nicht in Python 2, Python 3, das tun Sie) und weilgenerator
Objekte keine__getitem__
Methode.InformationsquelleAutor der Antwort Anaphory
Oft finde ich praktisch, in meine Skripte zu definieren, die eine
iterable
Funktion.(Beinhaltet nun Alfe vorgeschlagenen Vereinfachung):
so können Sie testen, ob ein beliebiges Objekt ist durchsuchbar in der sehr lesbaren form
als würden Sie mit der
callable
FunktionEDIT: wenn du numpy installiert haben, können Sie einfach tun:
numpy import iterable
das ist einfach etwas, wie
Wenn Sie nicht haben, numpy, können Sie einfach dieser code implementieren, oder die oben.
InformationsquelleAutor der Antwort fmonegaglia
pandas hat eine built-in Funktion wie:
InformationsquelleAutor der Antwort Sören
Seit Python 3.5 können Sie die Eingabe Modul aus der standard-Bibliothek für Typ-bezogene Dinge:
InformationsquelleAutor der Antwort Rotareti
Der einfachste Weg, wobei die Python -duck typingum den Fehler abzufangen (Python genau weiß, was es tut, erwarten Sie von einem Objekt zu einem iterator):
Hinweise:
__iter__
umgesetzt worden ist, wenn die exception-Typ ist die gleiche: jedenfalls werden Sie nicht in der Lage sein zu Durchlaufen Objekt.Ich glaube, ich verstehe Ihre Bedenken: Wie funktioniert
callable
existiert als eine Prüfung, wenn ich könnte verlassen sich ebenfalls auf duck typing, um eineAttributeError
wenn__call__
ist nicht definiert für mein Objekt, aber das ist nicht der Fall für die wiederholenden Prüfung?Ich kenne die Antwort nicht, aber Sie können entweder implementieren Sie die Funktion, die ich (und andere Nutzer) gab, oder einfach nur fangen Sie die exception in deinem code (Implementierung in diesem Teil werden wie die Funktion, die ich schrieb - nur sicherstellen, dass Sie isolieren das iterator-Kreation aus dem rest des Codes, so dass Sie capture die Ausnahme und unterscheiden es von anderen
TypeError
.InformationsquelleAutor der Antwort Luis Masuelli
Den
isiterable
func bei der folgende code gibtTrue
wenn ein Objekt ist iterierbar. wenn es nicht durchsuchbar zurückFalse
Beispiel
InformationsquelleAutor der Antwort Nomad
Diese wird ja sagen zu allen Arten von wiederholenden Objekte, aber es wird Nein sagen zu können strings in Python 2. (Das ist, was ich will, zum Beispiel, wenn eine rekursive Funktion könnte ein string oder ein container von strings. In dieser situation, um Vergebung zu bitten führen kann obfuscode, und es ist besser, Fragen Sie zuerst um Erlaubnis.)
Viele andere Strategien, die hier sagen Sie ja zu strings. Verwenden Sie Sie, wenn das, was Sie wollen.
Hinweis: is_iterable() wird ja sagen zu Zeichenfolgen des Typs
bytes
undbytearray
.bytes
Objekte in Python 3 sind iterierbarTrue == is_iterable(b"string") == is_iterable("string".encode('utf-8'))
Es gibt keine solche Art in Python 2.bytearray
Objekte in Python 2 und 3 sind iterierbarTrue == is_iterable(bytearray(b"abc"))
O. P.
hasattr(x, '__iter__')
Ansatz wird ja sagen, Zeichenketten in Python 3 und nicht in Python 2 (egal ob''
oderb''
oderu''
). Dank @LuisMasuelli zu bemerken, es wird auch lassen Sie sich auf ein buggy__iter__
.InformationsquelleAutor der Antwort Bob Stein
Abgesehen von regelmäßigen versuchen, außer, Sie könnten helfen.
Hilfe geben würde, die alle die Methoden, die ausgeführt werden könnte, die auf diesem Objekt(es könnte ein beliebiges Objekt und kann nicht eine Liste wie pro Beispiel), die temp in diesem Fall.
Hinweis: Dies wäre etwas, das Sie manuell tun.
InformationsquelleAutor der Antwort prudhvi Indana