Wie kann man in Python am besten testen, ob eine Variable eine Liste oder ein Tupel enthält? (dh eine Sammlung)
Ist isinstance()
so böse wie hier vorgeschlagen? http://www.canonical.org/~kragen/isinstance/
Update: Der häufigste Grund, warum ich eine Liste von einer Zeichenfolge unterscheiden möchte, ist, wenn ich eine unbegrenzt tief verschachtelte Baum- / Datenstruktur von Listen mit Listen von Listen mit Zeichenfolgen usw. habe, die ich mit einem rekursiven Algorithmus untersuche und die ich benötige zu wissen, wann ich die "Blatt" -Knoten getroffen habe.
Antworten:
Gehen Sie voran und verwenden
isinstance
Sie, wenn Sie es brauchen. Es ist etwas böse, da es benutzerdefinierte Sequenzen, Iteratoren und andere Dinge ausschließt, die Sie möglicherweise tatsächlich benötigen. Manchmal müssen Sie sich jedoch anders verhalten, wenn beispielsweise jemand eine Zeichenfolge übergibt. Meine Präferenz wäre es, explizit nachstr
oder zu suchenunicode
mögen:NB Verwechseln Sie nicht
types.StringType
mittypes.StringTypes
. Letzteres beinhaltetstr
undunicode
Objekte.Das
types
Modul wird von vielen als veraltet angesehen, da es nur direkt mit dem Objekttyp verglichen werden soll. Wenn Sie das oben Gesagte also lieber nicht verwenden möchten, können Sie alternativ explizit gegenstr
und prüfenunicode
wie :Bearbeiten:
Besser noch ist:
Bearbeitung beenden
Nach beiden können Sie sich wieder so verhalten, als ob Sie eine normale Sequenz erhalten, und Nicht-Sequenzen entsprechende Ausnahmen auslösen lassen.
Das "Böse" an der Typprüfung ist nicht, dass Sie sich für einen bestimmten Objekttyp möglicherweise anders verhalten möchten, sondern dass Sie Ihre Funktion künstlich daran hindern, das Richtige mit unerwarteten Objekttypen zu tun, die sonst das Richtige tun würden. Wenn Sie einen endgültigen Fallback haben, der nicht typgeprüft ist, entfernen Sie diese Einschränkung. Es sollte beachtet werden, dass zu viel Typprüfung ein Codegeruch ist, der darauf hinweist, dass Sie möglicherweise ein Refactoring durchführen möchten, aber das bedeutet nicht unbedingt, dass Sie es aus dem Getgo heraus vermeiden sollten.
quelle
str
Typ direkt verwenden, wenn Sie wirklich nach dem Typ suchen müssen , anstatttypes.StringType
nur einen Alias dafür zu verwenden. Aber ich glaube nicht, dass diese Antwort die gestellte Frage beantwortet, denn es ging um "eine Sammlung". Es sei denn, Sie verwenden eine Python, die neu genug ist, um dasabc
Modul zu haben , nach dem Sie nicht suchen könnenisinstance
, und selbst dann würde ich empfehlen, die Prüfung nach Möglichkeit zu vermeiden.assert isinstance(u'abc', str) == False
. Ich bin damit einverstanden, dass es besser ist, direkt mit dem Typ zu vergleichen, als dastypes
Modul zu verwenden, abertypes.StringTypes
etwas tut, dasstr
dies nicht tut: Es gibt True fürstr
undunicode
Objekte zurück. Ich werde meine Antwort bearbeiten, um alternativ eine doppelte Überprüfung anzubieten.isinstance
böse?" Und ich habe ein Gegenbeispiel gegeben, das (1) eine nicht böse Verwendung istisinstance
, weil ein Fallback bedeutet, dass das Ententyping nicht unterbrochen wird, und (2) eine gute Lösung für eine sehr häufige Motivation ist, die Menschen haben, um zu überprüfen, ob etwas ist einlist
odertuple
(dh um sie von Strings zu unterscheiden).class Foo(str): pass
was du willstquelle
type([]) is list
kehrt zurückTrue
type(x) in [list,tuple]
ist kürzer.Es ist nichts falsch daran zu benutzen
isinstance
, solange es nicht redundant ist. Wenn eine Variable nur eine Liste / ein Tupel sein soll, dokumentieren Sie die Schnittstelle und verwenden Sie sie einfach als solche. Ansonsten ist eine Überprüfung durchaus sinnvoll:Diese Art der Prüfung hat einige gute Anwendungsfälle, z. B. mit der Standardzeichenfolge Start mit / Ende mit (obwohl diese zur Genauigkeit in C in CPython mithilfe einer expliziten Überprüfung implementiert werden, um , ob es sich um ein Tupel handelt - es gibt mehrere Möglichkeiten um dieses Problem zu lösen, wie in dem Artikel erwähnt, auf den Sie verlinken).
Eine explizite Überprüfung ist oft besser als der Versuch, das Objekt als Container zu verwenden und die Ausnahme zu behandeln. Dies kann zu allen möglichen Problemen führen, wenn Code teilweise oder unnötig ausgeführt wird.
quelle
set
Objekt ist auch iterierbar, was bedeutet, dass Sie zwar Elemente daraus entfernen können, aber keine bestimmte Reihenfolge garantieren, was für bestimmte Algorithmen sehr gefährlich ist. In den Fällen, in denen die Reihenfolge der Elemente von Bedeutung ist, kann ein Algorithmus, der dieses Snippet verwendet, möglicherweise unterschiedliche Ergebnisse bei unterschiedlichen Läufen generieren!Dokumentieren Sie das Argument als eine Sequenz und verwenden Sie es als Sequenz. Überprüfen Sie nicht den Typ.
quelle
Wie wäre es mit :
hasattr(a, "__iter__")
?Es zeigt an, ob das zurückgegebene Objekt als Generator durchlaufen werden kann. Standardmäßig können Tupel und Listen, aber nicht die Zeichenfolgentypen.
quelle
__iter__
.__iter__
aus irgendeinem Grund ...Bei Python 2.8-
type(list) is list
Rückgabenfalse
würde ich vorschlagen, den Typ auf diese schreckliche Weise zu vergleichen:
(Nun, zumindest auf meinem System, mit Anaconda unter Mac OS X Yosemite)
quelle
type(list) is list
kehrt zurück,False
weiltype(list)
estype
nicht istlist
.type(list()) is list
oder mit einer anderen Instanz einer Liste wird zurückgegebenTrue
.Python verwendet "Duck Typing", dh wenn eine Variable wie eine Ente kakaks, muss es eine Ente sein. In Ihrem Fall möchten Sie wahrscheinlich, dass es iterierbar ist, oder Sie möchten über einen bestimmten Index auf das Element zugreifen. Sie sollten dies einfach tun: dh das Objekt in
for var:
odervar[idx]
innerhalb einestry
Blocks verwenden, und wenn Sie eine Ausnahme erhalten, war es keine Ente ...quelle
var
eine String-Iteration mit wahrscheinlich unerwarteten Ergebnissen auftritt.quelle
Wenn Sie nur wissen müssen, ob Sie die
foo[123]
Notation mit der Variablen verwenden können, können Sie überprüfen , ob ein__getitem__
Attribut vorhanden ist (das Python beim Zugriff per Index aufruft)hasattr(foo, '__getitem__')
quelle
Muss ein komplexerer Test sein, wenn Sie wirklich so ziemlich alles als Funktionsargument behandeln wollen.
Normalerweise reicht es jedoch aus, nur zu formulieren, dass eine Funktion iterabel erwartet, und dann nur zu überprüfen
type(a) != type('')
.Es kann auch vorkommen, dass Sie für eine Zeichenfolge einen einfachen Verarbeitungspfad haben oder dass Sie nett sind und einen Split usw. durchführen. Sie möchten also keine Zeichenfolgen anschreien, und wenn Ihnen jemand etwas Seltsames schickt, lassen Sie es ihn einfach haben eine Ausnahme.
quelle
Eine andere einfache Möglichkeit, herauszufinden, ob eine Variable entweder eine Liste oder ein Tupel ist oder im Allgemeinen den Variablentyp zu überprüfen, ist:
quelle
Im Prinzip stimme ich Ignacio oben zu, aber Sie können auch den Typ verwenden , um zu überprüfen, ob etwas ein Tupel oder eine Liste ist.
quelle