Python type() oder __class__, == oder
Möchte ich testen, ob ein Objekt eine Instanz einer Klasse und nur dieser Klasse (keine Unterklassen). Ich könnte es tun, entweder mit:
obj.__class__ == Foo
obj.__class__ is Foo
type(obj) == Foo
type(obj) is Foo
Gibt es Gründe für die Wahl der einen oder anderen? (performance-Unterschiede, Fallstricke, etc.)
In anderen Worten: ein) gibt es eine praktische Unterschied zwischen der Verwendung __class__
und type(x)
? b) sind die Objekte der Klasse immer sicher für den Vergleich mit is
?
Update: vielen Dank an alle für das feedback. Ich bin immer noch verwirrt, ob oder nicht die Objekte der Klasse sind singletons, mein gesunder Menschenverstand sagt Sie sind, aber es ist schon wirklich schwer zu bekommen eine Bestätigung (versuchen Sie googeln für "python", "Klasse" und "einzigartig" oder "singleton").
Ich möchte auch klarstellen, dass es für meine besonderen Bedürfnisse, der "billiger" - Lösung, die einfach funktioniert, ist die beste, da bin ich versucht zu optimieren, das beste aus dem wenigen, spezialisierten Klassen (fast der Punkt erreicht, wo die vernünftige Sache zu tun ist, um die drop-Python und entwickeln-Modul in C). Aber der Grund hinter der Frage war, besser zu verstehen die Sprache, weil einige seiner features sind ein bisschen zu unverständlich für mich zu finden, dass Informationen, die leicht. Das ist, warum ich bin, lassen die Diskussion erweitern Sie ein wenig, anstatt Abrechnung für __class__ is
so kann ich hören, die Meinung von erfahrenen Leuten. Bisher war es sehr fruchtbar!
Lief ich einen kleinen test zum benchmark die Leistung der 4 alternativen. Die profiler-Ergebnisse waren:
Python PyPy (4x)
type() is 2.138 2.594
__class__ is 2.185 2.437
type() == 2.213 2.625
__class__ == 2.271 2.453
Wenig überraschend ist, dass is
besser abgeschnitten als ==
für alle Fälle. type()
durchgeführt besser in Python (2% schneller) und __class__
durchgeführt besser in PyPy (6% schneller). Interessant zu beachten, dass __class__ ==
durchgeführt besser in PyPy als type() is
.
Update 2: viele Menschen scheinen nicht zu verstehen, was ich meine mit "eine Klasse ist ein singleton", so werde ich ilustrate mit einem Beispiel:
>>> class Foo(object): pass
...
>>> X = Foo
>>> class Foo(object): pass
...
>>> X == Foo
False
>>> isinstance(X(), Foo)
False
>>> isinstance(Foo(), X)
False
>>> x = type('Foo', (object,), dict())
>>> y = type('Foo', (object,), dict())
>>> x == y
False
>>> isinstance(x(), y)
False
>>> y = copy.copy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True
>>> y = copy.deepcopy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True
Ist es egal, ob es N Objekte vom Typ type
bei einem Objekt, nur einer wird seiner Klasse, daher ist es sicher im Vergleich zur Referenz in diesem Fall. Und da Referenz-Vergleich wird immer billiger sein als der Wert-Vergleich, wollte ich wissen, ob meine obige Behauptung hält. Ich bin dem erreichen der Schlussfolgerung, dass es funktioniert, es sei denn, jemand stellt Sie Beweise im Gegenteil.
InformationsquelleAutor der Frage mgibsonbr | 2012-03-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für old-style-Klassen, gibt es einen Unterschied:
Den point-of-new-style-Klassen, die Vereinheitlichung Klasse und Typ. Technisch gesehen, ist
__class__
ist die einzige Lösung, die funktioniert für neue und alte Stil, Klasse Instanzen, aber es wird auch eine Ausnahme geworfen, die auf old-style Klasse die Objekte selbst. Sie können rufen Sietype()
auf ein beliebiges Objekt, aber nicht jedes Objekt hat__class__
. Sie können auch dreck mit__class__
in einer Weise können Sie nicht muck mittype()
.Persönlich, ich haben in der Regel eine Umgebung mit new-style-Klassen, nur, und als eine Angelegenheit von Stil bevorzugen
type()
als ich in der Regel lieber built-in-Funktionen, wenn Sie existieren, um mit magischen Eigenschaften. Zum Beispiel, ich würde auch lieberbool(x)
zux.__nonzero__()
.InformationsquelleAutor der Antwort Michael Hoffman
Ergebnis
type()
entsprichtobj.__class__
im neuen style-Klassen, die Objekte der Klasse sind nicht sicher für den Vergleich mitis
verwenden==
statt.Für die neuen style-Klassen die bevorzugte Art und Weise hier wäre
type(obj) == Foo
.Als Michael Hoffman zeigte in seiner Antwort, es gibt einen Unterschied zwischen new und old-style-Klassen, so dass für rückwärts-kompatiblen code, den Sie verwenden müssen, um
obj.__class__ == Foo
.Für diejenigen, die behaupten, dass
isinstance(obj, Foo)
vorzuziehen ist, betrachten Sie das folgende Szenario:Der OP will das Verhalten von
type(obj) == Foo
wo wird es falsch sein, obwohlFoo
ist eine Basis-KlasseBar
.InformationsquelleAutor der Antwort Andrew Clark
is
sollte nur verwendet werden, für Kontrollen, die keine Typ-Prüfungen (es gibt eine Ausnahme von der Regel, wo Sie können und solltenis
für den check gegen singletons).Hinweis: würde ich generell nicht verwenden
type
und==
für Typ-Prüfungen, entweder. Die bevorzugte Art und Weise für Typ-Prüfungen istisinstance(obj, Foo)
. Wenn Sie jemals einen Grund haben, um zu überprüfen, ob etwas nicht in einer Unterklasse-Instanz, es riecht wie ein fischig-design zu mir. Wennclass Foo(Bar):
dannBar
ist einFoo
und Sie sollten vermeiden Sie alle Situationen, in denen einige Teil des Codes hat die Arbeit an einerFoo
Instanz, sondern bricht auf einemBar
Instanz.InformationsquelleAutor der Antwort wim
Kann ich bestätigen, dass
__instance__
ist ein singleton. Hier ist der Beweis.Wie Sie sehen können beide
t1
undt2
drucken Sie den gleichen Wert im Speicher, obwohlt1
undt2
sind verschiedene Werte im Speicher. Hier ist der Beweis, dass.Den
__instance__
Methode besteht nur dann, wenn Sie verwendet werdenclass "name"(object):
. Wenn Sie den klassischen Stil, Klasseclass "name":
als die__instance__
Methode nicht vorhanden.Was dies bedeutet ist, das die meisten generische, die Sie wahrscheinlich verwenden wollen
type
es sei denn, Sie wissen, für eine Tatsache Instanz existiert.InformationsquelleAutor der Antwort Zachary Kraus