Gibt es eine einfache Möglichkeit, festzustellen, ob eine Variable eine Liste, ein Wörterbuch oder etwas anderes ist? Ich bekomme ein Objekt zurück, das von beiden Typen sein kann, und ich muss in der Lage sein, den Unterschied zu erkennen.
python
dictionary
types
typeof
Justin Ethier
quelle
quelle
try
der nicht hilft. Wenn Sie beispielsweise wussten, dass ein Benutzer eine Zeichenfolge oder ein Array übergeben kann, sind beide indexfähig, aber dieser Index bedeutet etwas völlig anderes. In diesen Fällen scheitert es einfach auf unerwartete und seltsame Weise, sich auf einen Versuch zu verlassen. Eine Lösung besteht darin, eine separate Methode zu erstellen, eine andere darin, eine kleine Typprüfung hinzuzufügen. Ich persönlich bevorzuge polymorphes Verhalten gegenüber mehreren Methoden, die fast dasselbe tun ... aber das bin nur ich :)Antworten:
Es gibt zwei integrierte Funktionen, mit denen Sie den Typ eines Objekts identifizieren können. Sie verwenden können ,
type()
wenn Sie den genauen Typ eines Objekts benötigen, undisinstance()
zu überprüfen , ein Objekt der Art gegen etwas. Normalerweise möchten Sie dieisistance()
meiste Zeit verwenden, da es sehr robust ist und auch die Typvererbung unterstützt.Um den tatsächlichen Typ eines Objekts abzurufen, verwenden Sie die integrierte
type()
Funktion. Wenn Sie ein Objekt als einzigen Parameter übergeben, wird das Typobjekt dieses Objekts zurückgegeben:Dies funktioniert natürlich auch für benutzerdefinierte Typen:
Beachten Sie, dass
type()
nur der unmittelbare Typ des Objekts zurückgegeben wird, Sie jedoch nicht über die Typvererbung informiert werden können.Um dies abzudecken, sollten Sie die
isinstance
Funktion verwenden. Dies funktioniert natürlich auch für eingebaute Typen:isinstance()
Dies ist normalerweise die bevorzugte Methode, um den Typ eines Objekts sicherzustellen, da auch abgeleitete Typen akzeptiert werden. Wenn Sie das Typobjekt nicht tatsächlich benötigen (aus welchem Grund auch immer), wird die Verwendung der Verwendungisinstance()
vorgezogentype()
.Der zweite Parameter von
isinstance()
akzeptiert auch ein Tupel von Typen, sodass nach mehreren Typen gleichzeitig gesucht werden kann.isinstance
gibt dann true zurück, wenn das Objekt einen dieser Typen hat:quelle
is
anstatt==
wie die Typen sind Singletonsisinstance
ist sowieso die bevorzugte Form, daher wird keine==
oderis
keine verwendet.type
die beste Antwort ist. Es gibt Zeiten, in denenisinstance
die beste Antwort ist, und es gibt Zeiten, in denen das Tippen von Enten die beste Antwort ist. Es ist wichtig, alle Optionen zu kennen, damit Sie auswählen können, welche für die Situation besser geeignet ist.type(foo) is SomeType
es besser wäre alsisinstance(foo, SomeType)
.isinstance
für Ihren Anwendungsfall (Überprüfung auf eine Reihe von Typen) und mit verwenden können Ebenso eine saubere Syntax, die den großen Vorteil hat, dass Sie Unterklassen erfassen können. Jemand,OrderedDict
der Ihren Code verwendet, würde es hassen , wenn er fehlschlägt, weil er nur reine Diktate akzeptiert.Sie können dies tun mit
type()
:quelle
Es könnte pythonischer sein, einen
try
...except
Block zu verwenden. Auf diese Weise verhält sich eine Klasse, die wie eine Liste quakt oder wie ein Diktat quakt, unabhängig von ihrem tatsächlichen Typ ordnungsgemäß .Zur Verdeutlichung besteht die bevorzugte Methode zum "Erkennen des Unterschieds" zwischen Variablentypen in der sogenannten Ententypisierung : Solange die Methoden (und Rückgabetypen), auf die eine Variable reagiert, den Erwartungen Ihres Unterprogramms entsprechen, behandeln Sie sie so, wie Sie es erwarten sein. Wenn Sie beispielsweise eine Klasse haben, die die Klammeroperatoren mit
getattr
und überlastetsetattr
, aber ein lustiges internes Schema verwendet, ist es angemessen, dass sie sich wie ein Wörterbuch verhält, wenn sie dies zu emulieren versucht.Das andere Problem bei der
type(A) is type(B)
Überprüfung besteht darin, dass, wennA
es sich um eine Unterklasse von handeltB
, ausgewertet wird,false
wann dies programmgesteuert der Fall sein würdetrue
. Wenn ein Objekt eine Unterklasse einer Liste ist, sollte es wie eine Liste funktionieren: Wenn Sie den in der anderen Antwort angegebenen Typ überprüfen, wird dies verhindert. (isinstance
wird jedoch funktionieren).quelle
try
...except
ist eine gute Lösung, wenn Sie mit Fehlern umgehen möchten, aber nicht, wenn Sie sich für ein typbasiertes Verhalten entscheiden.Auf Instanzen von Objekten haben Sie auch die:
Attribut. Hier ist ein Beispiel aus der Python 3.3-Konsole
Beachten Sie, dass in Python 3.x und in New-Style-Klassen (optional in Python 2.6 verfügbar) Klasse und Typ zusammengeführt wurden und dies manchmal zu unerwarteten Ergebnissen führen kann. Hauptsächlich aus diesem Grund ist meine Lieblingsmethode zum Testen von Typen / Klassen die in isinstance integrierte Funktion.
quelle
__class__
ist in Python 2.x meistens in Ordnung. Die einzigen Objekte in Python, die kein__class__
Attribut haben , sind AFAIK-Klassen alten Stils. Ich verstehe Ihr Python 3-Problem übrigens nicht - in einer solchen Version hat nur jedes Objekt ein__class__
Attribut, das auf die richtige Klasse verweist.Bestimmen Sie den Typ eines Python-Objekts
Bestimmen Sie den Typ eines Objekts mit
type
Vermeiden Sie doppelte Unterstrichattribute wie
__class__
- sie sind nicht semantisch öffentlich, und obwohl dies in diesem Fall möglicherweise nicht der Fall ist, verhalten sich die integrierten Funktionen normalerweise besser.Typprüfung
Nun, das ist eine andere Frage, benutze keinen Typ - benutze
isinstance
:Dies deckt den Fall ab, in dem Ihr Benutzer durch Unterklassen möglicherweise etwas Kluges oder Sinnvolles tut
str
- gemäß dem Prinzip der Liskov-Substitution möchten Sie Unterklasseninstanzen verwenden können, ohne Ihren Code zu beschädigen - undisinstance
unterstützt dies.Verwenden Sie Abstraktionen
Noch besser ist es, wenn Sie nach einer bestimmten abstrakten Basisklasse suchen von
collections
odernumbers
:Oder einfach nicht explizit Typprüfung
Oder, vielleicht am besten, verwenden Sie die Enten-Typisierung und überprüfen Sie Ihren Code nicht explizit. Die Ententypisierung unterstützt die Liskov-Substitution mit mehr Eleganz und weniger Ausführlichkeit.
Fazit
type
diese Option, um die Klasse einer Instanz abzurufen.isinstance
diese Option, um explizit nach tatsächlichen Unterklassen oder registrierten Abstraktionen zu suchen.quelle
try
/except
anstatt explizit zu prüfen.Sie können
type()
oder verwendenisinstance()
.Seien Sie gewarnt, dass Sie Clobber
list
oder einen anderen Typ verwenden können, indem Sie eine Variable im aktuellen Bereich mit demselben Namen zuweisen.Oben sehen wir, dass
dict
eine Zeichenfolge neu zugewiesen wird, daher der Test:... schlägt fehl.
Um dies zu umgehen und
type()
vorsichtiger zu verwenden:quelle
dict
Zeichenfolge schlägt auch für viele andere Codes fehl, zdict([("key1", "value1"), ("key2", "value2")])
. Die Antwort auf diese Art von Problemen lautet "Dann tu das nicht" . Schattieren Sie keine eingebauten Typnamen und erwarten Sie, dass die Dinge richtig funktionieren.Obwohl die Fragen ziemlich alt sind, bin ich darauf gestoßen, als ich selbst einen richtigen Weg gefunden habe, und ich denke, es muss noch geklärt werden, zumindest für Python 2.x (habe Python 3 nicht überprüft, aber da das Problem bei klassischen Klassen auftritt welche auf solche version gegangen sind, spielt es wahrscheinlich keine rolle).
Hier versuche ich die Frage des Titels zu beantworten: Wie kann ich den Typ eines beliebigen Objekts bestimmen ? Andere Vorschläge zur Verwendung oder Nichtverwendung von isinstance sind in vielen Kommentaren und Antworten in Ordnung, aber ich gehe nicht auf diese Bedenken ein.
Das Hauptproblem bei diesem
type()
Ansatz ist, dass er mit Instanzen alten Stils nicht richtig funktioniert :Das Ausführen dieses Snippets würde ergeben:
Was, so argumentiere ich, nicht das ist, was die meisten Leute erwarten würden.
Der
__class__
Ansatz kommt der Korrektheit am nächsten, funktioniert jedoch in einem entscheidenden Fall nicht: Wenn das übergebene Objekt eine Klasse alten Stils ist (keine Instanz!), Da diesen Objekten ein solches Attribut fehlt.Dies ist der kleinste Codeausschnitt, den ich mir vorstellen kann, der eine solche legitime Frage auf konsistente Weise erfüllt:
quelle
Seien Sie vorsichtig mit isinstance
aber tippe
quelle
Neben den vorherigen Antworten ist zu erwähnen, dass es
collections.abc
mehrere abstrakte Basisklassen (ABCs) gibt, die die Ententypisierung ergänzen.Anstatt beispielsweise explizit zu überprüfen, ob es sich bei einer Liste um eine Liste handelt mit:
Wenn Sie nur sehen möchten, ob das Objekt, das Sie haben, das Abrufen von Elementen ermöglicht, können Sie Folgendes verwenden
collections.abc.Sequence
:Wenn Sie ausschließlich an Objekten interessiert sind, mit denen Elemente abgerufen , festgelegt und gelöscht werden können (dh veränderbare Sequenzen), entscheiden Sie sich für
collections.abc.MutableSequence
.Viele andere ABCs sind dort definiert,
Mapping
für Objekte , die als Karten verwendet werden können,Iterable
,Callable
, et cetera. Eine vollständige Liste aller dieser Elemente finden Sie in der Dokumentation zucollections.abc
.quelle
Im Allgemeinen können Sie eine Zeichenfolge aus einem Objekt mit dem Klassennamen extrahieren.
und zum Vergleich verwenden,
quelle
In vielen praktischen Fällen anstelle von
type
oder könnenisinstance
Sie auch verwenden@functools.singledispatch
, um allgemeine Funktionen zu definieren ( Funktion, die aus mehreren Funktionen besteht, die dieselbe Operation für verschiedene Typen implementieren ).Mit anderen Worten, Sie möchten es verwenden, wenn Sie einen Code wie den folgenden haben:
Hier ist ein kleines Beispiel, wie es funktioniert:
Zusätzlich können wir abstrakte Klassen verwenden , um mehrere Typen gleichzeitig abzudecken:
quelle
type()
ist eine bessere Lösung alsisinstance()
insbesondere fürbooleans
:True
undFalse
sind nur Schlüsselwörter, die bedeuten1
und0
in Python. Somit,und
beide kehren zurück
True
. Beide Booleschen Werte sind eine Instanz einer Ganzzahl.type()
ist jedoch klüger:kehrt zurück
False
.quelle